mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 04:22:13 +00:00
Compare commits
24 Commits
@vercel/st
...
@vercel-in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d312d85b2 | ||
|
|
10d4e51ac5 | ||
|
|
57231a0d60 | ||
|
|
e0e9cffc8d | ||
|
|
d0d0520111 | ||
|
|
9bb3067de2 | ||
|
|
decdf27fb5 | ||
|
|
4b376a564a | ||
|
|
b7e93524e3 | ||
|
|
62283356b8 | ||
|
|
3305f5e832 | ||
|
|
a938706916 | ||
|
|
b8bc682d3e | ||
|
|
f5ca497b75 | ||
|
|
b0898a6659 | ||
|
|
ab329f0fe8 | ||
|
|
8b35333446 | ||
|
|
a92467719b | ||
|
|
f6f16b0347 | ||
|
|
92ad73b8f3 | ||
|
|
849eedf0f2 | ||
|
|
848a62e4a5 | ||
|
|
cb784aeb9c | ||
|
|
3035e18fb6 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -10,7 +10,7 @@
|
||||
/packages/edge @vercel/compute
|
||||
/examples @leerob
|
||||
/examples/create-react-app @Timer
|
||||
/examples/nextjs @timneutkens @ijjk @styfle @ztanner
|
||||
/examples/nextjs @timneutkens @ijjk @styfle @ztanner @huozhi
|
||||
/examples/hugo @styfle
|
||||
/examples/jekyll @styfle
|
||||
/examples/zola @styfle
|
||||
|
||||
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
@@ -91,11 +91,18 @@ jobs:
|
||||
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||
FORCE_COLOR: '1'
|
||||
- name: 'Determing Turbo HIT or MISS'
|
||||
id: turbo-summary
|
||||
shell: bash
|
||||
run: |
|
||||
TURBO_MISS_COUNT=`node utils/determine-turbo-hit-or-miss.js`
|
||||
echo "MISS COUNT: $TURBO_MISS_COUNT"
|
||||
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
|
||||
- name: fetch ssl certificate after tests (linux, os x)
|
||||
if: matrix.runner != 'windows-latest'
|
||||
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
||||
- name: 'Upload Test Report to Datadog'
|
||||
if: always()
|
||||
if: ${{ steps['turbo-summary'].outputs.misses != '0' }}
|
||||
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
|
||||
env:
|
||||
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}
|
||||
|
||||
@@ -10,6 +10,8 @@ npm run dev
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
633
examples/nextjs/package-lock.json
generated
633
examples/nextjs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,17 +9,17 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "20.5.1",
|
||||
"@types/react": "18.2.20",
|
||||
"@types/node": "20.6.3",
|
||||
"@types/react": "18.2.22",
|
||||
"@types/react-dom": "18.2.7",
|
||||
"autoprefixer": "10.4.15",
|
||||
"eslint": "8.47.0",
|
||||
"eslint-config-next": "13.4.19",
|
||||
"next": "13.4.19",
|
||||
"postcss": "8.4.28",
|
||||
"eslint": "8.49.0",
|
||||
"eslint-config-next": "13.5.2",
|
||||
"next": "13.5.2",
|
||||
"postcss": "8.4.30",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"tailwindcss": "3.3.3",
|
||||
"typescript": "5.1.6"
|
||||
"typescript": "5.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
5
examples/remix/.gitignore
vendored
5
examples/remix/.gitignore
vendored
@@ -4,9 +4,4 @@ node_modules
|
||||
/build
|
||||
/public/build
|
||||
.env
|
||||
|
||||
.vercel
|
||||
.output
|
||||
|
||||
/api/index.js
|
||||
/api/index.js.map
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function App() {
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
</head>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import type { V2_MetaFunction } from "@vercel/remix";
|
||||
import type { MetaFunction } from "@vercel/remix";
|
||||
|
||||
export const meta: V2_MetaFunction = () => [{ title: "New Remix App" }];
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
{ title: "New Remix App" },
|
||||
{ name: "description", content: "Welcome to Remix!" },
|
||||
];
|
||||
};
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
|
||||
<h1>Welcome to Remix</h1>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { V2_MetaFunction } from "@vercel/remix";
|
||||
import type { MetaFunction } from "@vercel/remix";
|
||||
|
||||
export const config = { runtime: "edge" };
|
||||
|
||||
export const meta: V2_MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
|
||||
|
||||
export default function Edge() {
|
||||
return (
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
{
|
||||
"name": "my-remix-app",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "remix build",
|
||||
"dev": "remix dev",
|
||||
"start": "remix-serve build",
|
||||
"dev": "remix dev --manual",
|
||||
"start": "remix-serve ./build/index.js",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@remix-run/css-bundle": "^1.18.0",
|
||||
"@remix-run/node": "^1.18.0",
|
||||
"@remix-run/react": "^1.18.0",
|
||||
"@remix-run/serve": "^1.18.0",
|
||||
"@vercel/analytics": "^0.1.11",
|
||||
"@vercel/remix": "^1.18.0",
|
||||
"@remix-run/css-bundle": "^2.0.0",
|
||||
"@remix-run/node": "^2.0.0",
|
||||
"@remix-run/react": "^2.0.0",
|
||||
"@remix-run/serve": "^2.0.0",
|
||||
"@vercel/analytics": "^1.0.2",
|
||||
"@vercel/remix": "^2.0.0",
|
||||
"isbot": "^3.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^1.18.0",
|
||||
"@remix-run/eslint-config": "^1.18.0",
|
||||
"@types/react": "^18.0.25",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"eslint": "^8.28.0",
|
||||
"typescript": "^5.1.3"
|
||||
"@remix-run/dev": "^2.0.0",
|
||||
"@remix-run/eslint-config": "^2.0.0",
|
||||
"@types/react": "^18.2.20",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"eslint": "^8.38.0",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
/** @type {import('@remix-run/dev').AppConfig} */
|
||||
module.exports = {
|
||||
future: {
|
||||
v2_dev: true,
|
||||
v2_errorBoundary: true,
|
||||
v2_headers: true,
|
||||
v2_meta: true,
|
||||
v2_normalizeFormMethod: true,
|
||||
v2_routeConvention: true,
|
||||
},
|
||||
export default {
|
||||
ignoredRouteFiles: ["**/.*"],
|
||||
serverModuleFormat: "cjs",
|
||||
// appDirectory: "app",
|
||||
// assetsBuildDirectory: "public/build",
|
||||
// serverBuildPath: "build/index.js",
|
||||
// publicPath: "/build/",
|
||||
// serverBuildPath: "build/index.js",
|
||||
};
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES2019",
|
||||
"target": "ES2022",
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @vercel-internals/types
|
||||
|
||||
## 1.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||
- @vercel/build-utils@7.2.1
|
||||
|
||||
## 1.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
2
internals/types/index.d.ts
vendored
2
internals/types/index.d.ts
vendored
@@ -65,6 +65,8 @@ export type User = {
|
||||
billing: Billing;
|
||||
name?: string;
|
||||
limited?: boolean;
|
||||
version?: 'northstar';
|
||||
defaultTeamId?: string;
|
||||
};
|
||||
|
||||
export interface Team {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/types",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.11",
|
||||
"types": "index.d.ts",
|
||||
"main": "index.d.ts",
|
||||
"files": [
|
||||
@@ -10,7 +10,7 @@
|
||||
"dependencies": {
|
||||
"@types/node": "14.14.31",
|
||||
"@vercel-internals/constants": "1.0.4",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/routing-utils": "3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"source-map-support": "0.5.12",
|
||||
"ts-eager": "2.0.2",
|
||||
"ts-jest": "29.1.0",
|
||||
"turbo": "1.10.13",
|
||||
"turbo": "1.10.14",
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @vercel/build-utils
|
||||
|
||||
## 7.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
|
||||
|
||||
## 7.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "7.2.0",
|
||||
"version": "7.2.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -434,6 +434,13 @@ export interface Cron {
|
||||
schedule: string;
|
||||
}
|
||||
|
||||
// TODO: Proper description once complete
|
||||
export interface Flag {
|
||||
key: string;
|
||||
defaultValue?: unknown;
|
||||
metadata: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** The framework which created the function */
|
||||
export interface FunctionFramework {
|
||||
slug: string;
|
||||
@@ -458,6 +465,7 @@ export interface BuildResultV2Typical {
|
||||
framework?: {
|
||||
version: string;
|
||||
};
|
||||
flags?: Flag[];
|
||||
}
|
||||
|
||||
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# vercel
|
||||
|
||||
## 32.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [cli] Support northstar users ([#10535](https://github.com/vercel/vercel/pull/10535))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
|
||||
|
||||
- [speed insights] Prepare for migration to new speed insights package ([#10500](https://github.com/vercel/vercel/pull/10500))
|
||||
|
||||
- Updated dependencies [[`b0898a665`](https://github.com/vercel/vercel/commit/b0898a66591d5296dc38ffcf0e8345c9338b72f3), [`10d4e51ac`](https://github.com/vercel/vercel/commit/10d4e51ac57b76f05ddc0bf3adf220e2490244fc), [`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3), [`f5ca497b7`](https://github.com/vercel/vercel/commit/f5ca497b7522a2dad637cef238da9716ac133057), [`ab329f0fe`](https://github.com/vercel/vercel/commit/ab329f0fe88e9cb72607d0cba41f5e168d77e077), [`d0d052011`](https://github.com/vercel/vercel/commit/d0d0520111264434d57d5920de0f622f6a2588dc), [`9bb3067de`](https://github.com/vercel/vercel/commit/9bb3067de28be77f3ce268a31a7aa6184836dfb1)]:
|
||||
- @vercel/static-build@2.0.7
|
||||
- @vercel/node@3.0.6
|
||||
- @vercel/build-utils@7.2.1
|
||||
- @vercel/next@4.0.7
|
||||
- @vercel/python@4.0.2
|
||||
- @vercel/redwood@2.0.3
|
||||
- @vercel/remix-builder@2.0.7
|
||||
- @vercel/go@3.0.2
|
||||
|
||||
## 32.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`849eedf0f`](https://github.com/vercel/vercel/commit/849eedf0f2841211e4175d374f1cf01330bf9611), [`f6f16b034`](https://github.com/vercel/vercel/commit/f6f16b0347bac9f5c33c79ccb1fb9fd9d254cae5), [`3035e18fb`](https://github.com/vercel/vercel/commit/3035e18fb67dfe7031e235a74136a41948f86d5a), [`cb784aeb9`](https://github.com/vercel/vercel/commit/cb784aeb9c9e4eddf1c65b61849a87edb1117af1)]:
|
||||
- @vercel/next@4.0.6
|
||||
- @vercel/remix-builder@2.0.6
|
||||
|
||||
## 32.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "32.2.4",
|
||||
"version": "32.3.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -31,16 +31,16 @@
|
||||
"node": ">= 16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/go": "3.0.1",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/go": "3.0.2",
|
||||
"@vercel/hydrogen": "1.0.1",
|
||||
"@vercel/next": "4.0.5",
|
||||
"@vercel/node": "3.0.5",
|
||||
"@vercel/python": "4.0.1",
|
||||
"@vercel/redwood": "2.0.2",
|
||||
"@vercel/remix-builder": "2.0.5",
|
||||
"@vercel/next": "4.0.7",
|
||||
"@vercel/node": "3.0.6",
|
||||
"@vercel/python": "4.0.2",
|
||||
"@vercel/redwood": "2.0.3",
|
||||
"@vercel/remix-builder": "2.0.7",
|
||||
"@vercel/ruby": "2.0.2",
|
||||
"@vercel/static-build": "2.0.6"
|
||||
"@vercel/static-build": "2.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alex_neo/jest-expect-message": "1.0.5",
|
||||
@@ -86,8 +86,8 @@
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel-internals/constants": "1.0.4",
|
||||
"@vercel-internals/get-package-json": "1.0.0",
|
||||
"@vercel-internals/types": "1.0.10",
|
||||
"@vercel/client": "13.0.3",
|
||||
"@vercel-internals/types": "1.0.11",
|
||||
"@vercel/client": "13.0.4",
|
||||
"@vercel/error-utils": "2.0.1",
|
||||
"@vercel/frameworks": "2.0.2",
|
||||
"@vercel/fs-detectors": "5.1.0",
|
||||
|
||||
@@ -27,7 +27,7 @@ export const help = () => `
|
||||
pull [path] Pull your Project Settings from the cloud
|
||||
redeploy [url|id] Rebuild and deploy a previous deployment.
|
||||
rollback [url|id] Quickly revert back to a previous deployment
|
||||
switch [scope] Switches between teams and your personal account
|
||||
switch [scope] Switches between different scopes
|
||||
|
||||
${chalk.dim('Advanced')}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
NowBuildError,
|
||||
Cron,
|
||||
validateNpmrc,
|
||||
Flag,
|
||||
} from '@vercel/build-utils';
|
||||
import {
|
||||
detectBuilders,
|
||||
@@ -93,6 +94,7 @@ interface BuildOutputConfig {
|
||||
version: string;
|
||||
};
|
||||
crons?: Cron[];
|
||||
flags?: Flag[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,6 +428,23 @@ async function doBuild(
|
||||
|
||||
const ops: Promise<Error | void>[] = [];
|
||||
|
||||
const dependencies = [
|
||||
...Object.keys(pkg?.dependencies ?? {}),
|
||||
...Object.keys(pkg?.devDependencies ?? {}),
|
||||
];
|
||||
|
||||
const isUsingSpeedInsights = dependencies.some(
|
||||
d => d === '@vercel/speed-insights'
|
||||
);
|
||||
|
||||
if (isUsingSpeedInsights && process.env.VERCEL_ANALYTICS_ID) {
|
||||
output.warn(
|
||||
`The \`VERCEL_ANALYTICS_ID\` environment variable is deprecated and will be removed in a future release. Please remove it from your environment variables`
|
||||
);
|
||||
|
||||
delete process.env.VERCEL_ANALYTICS_ID;
|
||||
}
|
||||
|
||||
// Write the `detectedBuilders` result to output dir
|
||||
const buildsJsonBuilds = new Map<Builder, SerializedBuilder>(
|
||||
builds.map(build => {
|
||||
@@ -627,6 +646,7 @@ async function doBuild(
|
||||
const mergedWildcard = mergeWildcard(buildResults.values());
|
||||
const mergedOverrides: Record<string, PathOverride> =
|
||||
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
||||
const mergedFlags = mergeFlags(buildResults.values());
|
||||
|
||||
const framework = await getFramework(cwd, buildResults);
|
||||
|
||||
@@ -640,6 +660,7 @@ async function doBuild(
|
||||
overrides: mergedOverrides,
|
||||
framework,
|
||||
crons: mergedCrons,
|
||||
flags: mergedFlags,
|
||||
};
|
||||
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
|
||||
|
||||
@@ -774,3 +795,15 @@ function mergeWildcard(
|
||||
}
|
||||
return wildcard;
|
||||
}
|
||||
|
||||
function mergeFlags(
|
||||
buildResults: Iterable<BuildResult | BuildOutputConfig>
|
||||
): BuildResultV2Typical['flags'] {
|
||||
return Array.from(buildResults).flatMap(result => {
|
||||
if ('flags' in result) {
|
||||
return result.flags ?? [];
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ export const domainsCommand: Command = {
|
||||
},
|
||||
{
|
||||
name: 'move',
|
||||
description: 'Move a domain to another user or team',
|
||||
description: 'Move a domain to another scope',
|
||||
arguments: [
|
||||
{
|
||||
name: 'name',
|
||||
|
||||
@@ -53,6 +53,12 @@ export default async function move(
|
||||
|
||||
const teams = await getTeams(client);
|
||||
const matchId = await findDestinationMatch(destination, user, teams);
|
||||
|
||||
if (matchId && matchId === user.id && user.version === 'northstar') {
|
||||
output.error(`You may not move your domain to your user account.`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!matchId && !opts['--yes']) {
|
||||
output.warn(
|
||||
`You're not a member of ${param(destination)}. ` +
|
||||
|
||||
7
packages/cli/src/commands/env/pull.ts
vendored
7
packages/cli/src/commands/env/pull.ts
vendored
@@ -55,6 +55,12 @@ function tryReadHeadSync(path: string, length: number) {
|
||||
}
|
||||
}
|
||||
|
||||
const VARIABLES_TO_IGNORE = [
|
||||
'VERCEL_ANALYTICS_ID',
|
||||
'VERCEL_SPEED_INSIGHTS_ID',
|
||||
'VERCEL_WEB_ANALYTICS_ID',
|
||||
];
|
||||
|
||||
export default async function pull(
|
||||
client: Client,
|
||||
link: ProjectLinked,
|
||||
@@ -131,6 +137,7 @@ export default async function pull(
|
||||
CONTENTS_PREFIX +
|
||||
Object.keys(records)
|
||||
.sort()
|
||||
.filter(key => !VARIABLES_TO_IGNORE.includes(key))
|
||||
.map(key => `${key}="${escapeValue(records[key])}"`)
|
||||
.join('\n') +
|
||||
'\n';
|
||||
|
||||
@@ -19,6 +19,7 @@ import Client from '../../util/client';
|
||||
import { LoginResult } from '../../util/login/types';
|
||||
import { help } from '../help';
|
||||
import { loginCommand } from './command';
|
||||
import { updateCurrentTeamAfterLogin } from '../../util/login/update-current-team-after-login';
|
||||
|
||||
export default async function login(client: Client): Promise<number> {
|
||||
const { output } = client;
|
||||
@@ -67,20 +68,16 @@ export default async function login(client: Client): Promise<number> {
|
||||
return result;
|
||||
}
|
||||
|
||||
// If the token was upgraded (not a new login), then don't modify
|
||||
// the current scope.
|
||||
if (!client.authConfig.token) {
|
||||
if (result.teamId) {
|
||||
// SSO login, so set the current scope to the appropriate Team
|
||||
client.config.currentTeam = result.teamId;
|
||||
} else {
|
||||
delete client.config.currentTeam;
|
||||
}
|
||||
}
|
||||
const isNewLogin = !client.authConfig.token;
|
||||
|
||||
// Save the user's authentication token to the configuration file.
|
||||
client.authConfig.token = result.token;
|
||||
|
||||
// If we have a new login, update `currentTeam`
|
||||
if (isNewLogin) {
|
||||
await updateCurrentTeamAfterLogin(client, output, result.teamId);
|
||||
}
|
||||
|
||||
writeToAuthConfigFile(client.authConfig);
|
||||
writeToConfigFile(client.config);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { packageName } from '../../util/pkg-name';
|
||||
|
||||
export const logoutCommand: Command = {
|
||||
name: 'logout',
|
||||
description: 'Logout the current authenticated user or team.',
|
||||
description: 'Logout the current authenticated user.',
|
||||
arguments: [],
|
||||
options: [],
|
||||
examples: [
|
||||
|
||||
@@ -13,7 +13,7 @@ export const projectCommand: Command = {
|
||||
subcommands: [
|
||||
{
|
||||
name: 'ls',
|
||||
description: 'Show all projects in the selected team/user',
|
||||
description: 'Show all projects in the selected scope',
|
||||
arguments: [],
|
||||
options: [],
|
||||
examples: [],
|
||||
|
||||
@@ -39,11 +39,12 @@ export default async function list(client: Client): Promise<number> {
|
||||
apiVersion: 2,
|
||||
});
|
||||
let { currentTeam } = config;
|
||||
const accountIsCurrent = !currentTeam;
|
||||
|
||||
output.spinner('Fetching user information');
|
||||
const user = await getUser(client);
|
||||
|
||||
const accountIsCurrent = !currentTeam && user.version !== 'northstar';
|
||||
|
||||
if (accountIsCurrent) {
|
||||
currentTeam = user.id;
|
||||
}
|
||||
@@ -55,12 +56,14 @@ export default async function list(client: Client): Promise<number> {
|
||||
current: id === currentTeam ? chars.tick : '',
|
||||
}));
|
||||
|
||||
teamList.unshift({
|
||||
id: user.id,
|
||||
name: user.email,
|
||||
value: user.username || user.email,
|
||||
current: accountIsCurrent ? chars.tick : '',
|
||||
});
|
||||
if (user.version !== 'northstar') {
|
||||
teamList.unshift({
|
||||
id: user.id,
|
||||
name: user.email,
|
||||
value: user.username || user.email,
|
||||
current: accountIsCurrent ? chars.tick : '',
|
||||
});
|
||||
}
|
||||
|
||||
// Bring the current Team to the beginning of the list
|
||||
if (!accountIsCurrent) {
|
||||
@@ -71,18 +74,21 @@ export default async function list(client: Client): Promise<number> {
|
||||
|
||||
// Printing
|
||||
output.stopSpinner();
|
||||
console.log(); // empty line
|
||||
client.stdout.write('\n'); // empty line
|
||||
|
||||
table(
|
||||
['', 'id', 'email / name'],
|
||||
teamList.map(team => [team.current, team.value, team.name]),
|
||||
[1, 5]
|
||||
[1, 5],
|
||||
(str: string) => {
|
||||
client.stdout.write(str);
|
||||
}
|
||||
);
|
||||
|
||||
if (pagination?.count === 20) {
|
||||
const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);
|
||||
const nextCmd = `${packageName} teams ls${flags} --next ${pagination.next}`;
|
||||
console.log(); // empty line
|
||||
client.stdout.write('\n'); // empty line
|
||||
output.log(`To display the next page run ${cmd(nextCmd)}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,14 +70,21 @@ export default async function main(client: Client, desiredSlug?: string) {
|
||||
suffix += ` ${emoji('locked')}`;
|
||||
}
|
||||
|
||||
const personalAccountChoice =
|
||||
user.version === 'northstar'
|
||||
? []
|
||||
: [
|
||||
{ separator: 'Personal Account' },
|
||||
{
|
||||
name: `${user.name || user.email} (${user.username})${suffix}`,
|
||||
value: user.username,
|
||||
short: user.username,
|
||||
selected: personalScopeSelected,
|
||||
},
|
||||
];
|
||||
|
||||
const choices = [
|
||||
{ separator: 'Personal Account' },
|
||||
{
|
||||
name: `${user.name || user.email} (${user.username})${suffix}`,
|
||||
value: user.username,
|
||||
short: user.username,
|
||||
selected: personalScopeSelected,
|
||||
},
|
||||
...personalAccountChoice,
|
||||
{ separator: 'Teams' },
|
||||
...teamChoices,
|
||||
];
|
||||
@@ -97,6 +104,11 @@ export default async function main(client: Client, desiredSlug?: string) {
|
||||
}
|
||||
|
||||
if (desiredSlug === user.username || desiredSlug === user.email) {
|
||||
if (user.version === 'northstar') {
|
||||
output.error('You cannot set your Personal Account as the scope.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Switch to user's personal account
|
||||
if (personalScopeSelected) {
|
||||
output.log('No changes made');
|
||||
|
||||
@@ -56,6 +56,7 @@ import { ProxyAgent } from 'proxy-agent';
|
||||
import box from './util/output/box';
|
||||
import { execExtension } from './util/extension/exec';
|
||||
import { help } from './args';
|
||||
import { updateCurrentTeamAfterLogin } from './util/login/update-current-team-after-login';
|
||||
|
||||
const VERCEL_DIR = getGlobalPathConfig();
|
||||
const VERCEL_CONFIG_PATH = configFiles.getConfigFilePath();
|
||||
@@ -337,17 +338,12 @@ const main = async () => {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result.teamId) {
|
||||
// SSO login, so set the current scope to the appropriate Team
|
||||
client.config.currentTeam = result.teamId;
|
||||
} else {
|
||||
delete client.config.currentTeam;
|
||||
}
|
||||
|
||||
// When `result` is a string it's the user's authentication token.
|
||||
// It needs to be saved to the configuration file.
|
||||
client.authConfig.token = result.token;
|
||||
|
||||
await updateCurrentTeamAfterLogin(client, output, result.teamId);
|
||||
|
||||
configFiles.writeToAuthConfigFile(client.authConfig);
|
||||
configFiles.writeToConfigFile(client.config);
|
||||
|
||||
@@ -447,6 +443,11 @@ const main = async () => {
|
||||
}
|
||||
|
||||
if (user.id === scope || user.email === scope || user.username === scope) {
|
||||
if (user.version === 'northstar') {
|
||||
output.error('You cannot set your Personal Account as the scope.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
delete client.config.currentTeam;
|
||||
} else {
|
||||
let teams = [];
|
||||
|
||||
@@ -59,7 +59,7 @@ export class TeamDeleted extends NowError<'TEAM_DELETED', {}> {
|
||||
constructor() {
|
||||
super({
|
||||
code: 'TEAM_DELETED',
|
||||
message: `Your team was deleted. You can switch to a different one using ${getCommandName(
|
||||
message: `Your team was deleted or you were removed from the team. You can switch to a different one using ${getCommandName(
|
||||
`switch`
|
||||
)}.`,
|
||||
meta: {},
|
||||
|
||||
@@ -15,9 +15,12 @@ export default async function getScope(
|
||||
const user = await getUser(client);
|
||||
let contextName = user.username || user.email;
|
||||
let team: Team | null = null;
|
||||
const defaultTeamId =
|
||||
user.version === 'northstar' ? user.defaultTeamId : undefined;
|
||||
const currentTeamOrDefaultTeamId = client.config.currentTeam || defaultTeamId;
|
||||
|
||||
if (client.config.currentTeam && opts.getTeam !== false) {
|
||||
team = await getTeamById(client, client.config.currentTeam);
|
||||
if (currentTeamOrDefaultTeamId && opts.getTeam !== false) {
|
||||
team = await getTeamById(client, currentTeamOrDefaultTeamId);
|
||||
|
||||
if (!team) {
|
||||
throw new TeamDeleted();
|
||||
|
||||
@@ -25,11 +25,18 @@ export default async function selectOrg(
|
||||
output.stopSpinner();
|
||||
}
|
||||
|
||||
const personalAccountChoice =
|
||||
user.version === 'northstar'
|
||||
? []
|
||||
: [
|
||||
{
|
||||
name: user.name || user.username,
|
||||
value: { type: 'user', id: user.id, slug: user.username },
|
||||
} as const,
|
||||
];
|
||||
|
||||
const choices: Choice[] = [
|
||||
{
|
||||
name: user.name || user.username,
|
||||
value: { type: 'user', id: user.id, slug: user.username },
|
||||
},
|
||||
...personalAccountChoice,
|
||||
...teams.map<Choice>(team => ({
|
||||
name: team.name || team.slug,
|
||||
value: { type: 'team', id: team.id, slug: team.slug },
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import type Client from '../client';
|
||||
import type { Output } from '../output';
|
||||
import getUser from '../get-user';
|
||||
|
||||
// NOTE: `client.authConfig.token` must be set before calling this
|
||||
export async function updateCurrentTeamAfterLogin(
|
||||
client: Client,
|
||||
output: Output,
|
||||
ssoTeamId?: string
|
||||
) {
|
||||
if (ssoTeamId) {
|
||||
client.config.currentTeam = ssoTeamId;
|
||||
} else {
|
||||
let user = null;
|
||||
try {
|
||||
user = await getUser(client);
|
||||
} catch (err: unknown) {
|
||||
// Shouldn't happen since we just logged in
|
||||
output.error('Failed to fetch the logged in user. Please try again.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (user.version === 'northstar' && user.defaultTeamId) {
|
||||
client.config.currentTeam = user.defaultTeamId;
|
||||
} else {
|
||||
delete client.config.currentTeam;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@ const printLine = (data: string[], sizes: number[]) =>
|
||||
export default function table(
|
||||
fieldNames: string[] = [],
|
||||
data: string[][] = [],
|
||||
margins: number[] = []
|
||||
margins: number[] = [],
|
||||
print: (str: string) => void
|
||||
) {
|
||||
// Compute size of each column
|
||||
const sizes = data
|
||||
@@ -26,10 +27,12 @@ export default function table(
|
||||
.map((size, i) => (i < margins.length && size + margins[i]) || size);
|
||||
|
||||
// Print header
|
||||
console.log(chalk.grey(printLine(fieldNames, sizes)));
|
||||
print(chalk.grey(printLine(fieldNames, sizes)));
|
||||
print('\n');
|
||||
|
||||
// Print content
|
||||
for (const row of data) {
|
||||
console.log(printLine(row, sizes));
|
||||
print(printLine(row, sizes));
|
||||
print('\n');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,6 +415,24 @@ module.exports = async function prepare(session, binaryPath, tmpFixturesDir) {
|
||||
projectId: 'QmRoBYhejkkmssotLZr8tWgewPdPcjYucYUNERFbhJrRNi',
|
||||
}),
|
||||
},
|
||||
'vc-build-speed-insights': {
|
||||
'.vercel/project.json': JSON.stringify({
|
||||
orgId: '.',
|
||||
projectId: '.',
|
||||
settings: {
|
||||
framework: null,
|
||||
installCommand: 'echo "skipping install"',
|
||||
},
|
||||
}),
|
||||
'package.json': JSON.stringify({
|
||||
scripts: {
|
||||
build: 'mkdir -p public && echo hi > public/index.txt',
|
||||
},
|
||||
dependencies: {
|
||||
'@vercel/speed-insights': '0.0.1',
|
||||
},
|
||||
}),
|
||||
},
|
||||
'vc-build-static-build': {
|
||||
'.vercel/project.json': JSON.stringify({
|
||||
orgId: '.',
|
||||
|
||||
3
packages/cli/test/integration-1.test.ts
vendored
3
packages/cli/test/integration-1.test.ts
vendored
@@ -16,7 +16,6 @@ import {
|
||||
import formatOutput from './helpers/format-output';
|
||||
import type http from 'http';
|
||||
import type { CLIProcess } from './helpers/types';
|
||||
import type {} from './helpers/types';
|
||||
const TEST_TIMEOUT = 3 * 60 * 1000;
|
||||
jest.setTimeout(TEST_TIMEOUT);
|
||||
|
||||
@@ -105,6 +104,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
query.email === email
|
||||
) {
|
||||
res.end(JSON.stringify({ token }));
|
||||
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||
res.end(JSON.stringify({ user: { email } }));
|
||||
} else {
|
||||
res.statusCode = 405;
|
||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||
|
||||
18
packages/cli/test/integration-2.test.ts
vendored
18
packages/cli/test/integration-2.test.ts
vendored
@@ -79,6 +79,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
query.email === email
|
||||
) {
|
||||
res.end(JSON.stringify({ token }));
|
||||
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||
res.end(JSON.stringify({ user: { email } }));
|
||||
} else {
|
||||
res.statusCode = 405;
|
||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||
@@ -1152,6 +1154,22 @@ test('[vc build] should build project with `@vercel/static-build`', async () =>
|
||||
expect(builds.builds[0].use).toBe('@vercel/static-build');
|
||||
});
|
||||
|
||||
test('[vc build] should build project with `@vercel/speed-insights`', async () => {
|
||||
try {
|
||||
process.env.VERCEL_ANALYTICS_ID = '123';
|
||||
|
||||
const directory = await setupE2EFixture('vc-build-speed-insights');
|
||||
const output = await execCli(binaryPath, ['build'], { cwd: directory });
|
||||
expect(output.exitCode, formatOutput(output)).toBe(0);
|
||||
expect(output.stderr).toContain('Build Completed in .vercel/output');
|
||||
expect(output.stderr).toContain(
|
||||
'The `VERCEL_ANALYTICS_ID` environment variable is deprecated and will be removed in a future release. Please remove it from your environment variables'
|
||||
);
|
||||
} finally {
|
||||
delete process.env.VERCEL_ANALYTICS_ID;
|
||||
}
|
||||
});
|
||||
|
||||
test('[vc build] should not include .vercel when distDir is "."', async () => {
|
||||
const directory = await setupE2EFixture('static-build-dist-dir');
|
||||
const output = await execCli(binaryPath, ['build'], { cwd: directory });
|
||||
|
||||
2
packages/cli/test/integration-3.test.ts
vendored
2
packages/cli/test/integration-3.test.ts
vendored
@@ -89,6 +89,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
query.email === email
|
||||
) {
|
||||
res.end(JSON.stringify({ token }));
|
||||
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||
res.end(JSON.stringify({ user: { email } }));
|
||||
} else {
|
||||
res.statusCode = 405;
|
||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||
|
||||
@@ -40,3 +40,15 @@ export function useDomains() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function useDomain(postfix: string) {
|
||||
client.scenario.get(
|
||||
`/v4/domains/${encodeURIComponent(`example-${postfix}.com`)}`,
|
||||
(req, res) => {
|
||||
const domain = createDomain(postfix);
|
||||
res.json({
|
||||
domain,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ export function useTeams(
|
||||
failMissingToken?: boolean;
|
||||
failInvalidToken?: boolean;
|
||||
failNoAccess?: boolean;
|
||||
apiVersion?: number;
|
||||
} = {
|
||||
failMissingToken: false,
|
||||
failInvalidToken: false,
|
||||
failNoAccess: false,
|
||||
apiVersion: 1,
|
||||
}
|
||||
) {
|
||||
const id = teamId || chance().guid();
|
||||
@@ -59,11 +61,11 @@ export function useTeams(
|
||||
});
|
||||
}
|
||||
|
||||
client.scenario.get('/v1/teams', (_req, res) => {
|
||||
client.scenario.get(`/v${options.apiVersion}/teams`, (_req, res) => {
|
||||
res.json({
|
||||
teams,
|
||||
});
|
||||
});
|
||||
|
||||
return teams;
|
||||
return options.apiVersion === 2 ? { teams } : teams;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import chance from 'chance';
|
||||
import { client } from './client';
|
||||
import type { User } from '@vercel-internals/types';
|
||||
|
||||
export function useUser() {
|
||||
export function useUser(additionalAttrs: Partial<User> = {}) {
|
||||
const user = {
|
||||
id: chance().guid(),
|
||||
email: chance().email(),
|
||||
name: chance().name(),
|
||||
username: chance().first().toLowerCase(),
|
||||
...additionalAttrs,
|
||||
};
|
||||
client.scenario.get('/v2/user', (_req, res) => {
|
||||
res.json({
|
||||
|
||||
173
packages/cli/test/northstar.test.ts
vendored
Normal file
173
packages/cli/test/northstar.test.ts
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
import type http from 'http';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { parse as parseUrl } from 'url';
|
||||
import { execCli } from './helpers/exec';
|
||||
import waitForPrompt from './helpers/wait-for-prompt';
|
||||
import getGlobalDir from './helpers/get-global-dir';
|
||||
import { listTmpDirs } from './helpers/get-tmp-dir';
|
||||
import formatOutput from './helpers/format-output';
|
||||
import { User } from '@vercel-internals/types';
|
||||
|
||||
const binaryPath = path.resolve(__dirname, `../scripts/start.js`);
|
||||
|
||||
function getGlobalConfigPath() {
|
||||
return path.join(getGlobalDir(), 'config.json');
|
||||
}
|
||||
|
||||
function getConfigAuthPath() {
|
||||
return path.join(getGlobalDir(), 'auth.json');
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await fs.remove(getGlobalConfigPath());
|
||||
await fs.remove(getConfigAuthPath());
|
||||
} catch (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (localApiServer) {
|
||||
localApiServer.close();
|
||||
}
|
||||
|
||||
const allTmpDirs = listTmpDirs();
|
||||
for (const tmpDir of allTmpDirs) {
|
||||
tmpDir.removeCallback();
|
||||
}
|
||||
});
|
||||
|
||||
function mockApi(user: Partial<User>) {
|
||||
return function (req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
const { url = '/', method } = req;
|
||||
let { pathname = '/', query = {} } = parseUrl(url, true);
|
||||
const securityCode = 'Bears Beets Battlestar Galactica';
|
||||
res.setHeader('content-type', 'application/json');
|
||||
if (
|
||||
method === 'POST' &&
|
||||
pathname === '/registration' &&
|
||||
query.mode === 'login'
|
||||
) {
|
||||
res.end(JSON.stringify({ token: 'test', securityCode }));
|
||||
} else if (
|
||||
method === 'GET' &&
|
||||
pathname === '/registration/verify' &&
|
||||
query.email === user.email
|
||||
) {
|
||||
res.end(JSON.stringify({ token: 'test' }));
|
||||
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||
res.end(JSON.stringify({ user }));
|
||||
} else {
|
||||
res.statusCode = 405;
|
||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let localApiServer: any;
|
||||
function setupLocalApiServer(user: Partial<User>) {
|
||||
return new Promise<string>(resolve => {
|
||||
localApiServer = require('http')
|
||||
.createServer(mockApi(user))
|
||||
.listen(0, () => {
|
||||
const { port } = localApiServer.address();
|
||||
const loginApiUrl = `http://localhost:${port}`;
|
||||
resolve(loginApiUrl);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loginSteps(
|
||||
vercel: ReturnType<typeof execCli>,
|
||||
user: Partial<User>
|
||||
) {
|
||||
await waitForPrompt(vercel, 'Continue with Email');
|
||||
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||
vercel.stdin?.write('\r'); // Return key
|
||||
await waitForPrompt(vercel, 'Enter your email address');
|
||||
vercel.stdin?.write(user.email);
|
||||
vercel.stdin?.write('\r');
|
||||
await waitForPrompt(
|
||||
vercel,
|
||||
`Email authentication complete for ${user.email}`
|
||||
);
|
||||
return vercel;
|
||||
}
|
||||
|
||||
describe('CLI initialization', () => {
|
||||
describe('login required before running a command', () => {
|
||||
describe('non-northstar', () => {
|
||||
const user = {
|
||||
id: 'test-id',
|
||||
username: 'test-username',
|
||||
email: 'test@example.com',
|
||||
};
|
||||
|
||||
it('should not set currentTeam to defaultTeamId', async () => {
|
||||
const loginApiUrl = await setupLocalApiServer(user);
|
||||
const vercel = execCli(
|
||||
binaryPath,
|
||||
['domains', 'invalidSubCommand', '--api', loginApiUrl],
|
||||
{ env: { FORCE_TTY: '1' } }
|
||||
);
|
||||
const steps = loginSteps(vercel, user);
|
||||
await waitForPrompt(vercel, 'Please specify a valid subcommand');
|
||||
const output = await steps;
|
||||
expect(output.exitCode, formatOutput(output)).toBe(2);
|
||||
const config = await fs.readJSON(getGlobalConfigPath());
|
||||
expect(config.currentTeam).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
const user = {
|
||||
id: 'test-id',
|
||||
username: 'test-username',
|
||||
email: 'test@example.com',
|
||||
version: 'northstar',
|
||||
defaultTeamId: 'test-default-team-id',
|
||||
};
|
||||
it('should set currentTeam to defaultTeamId', async () => {
|
||||
const loginApiUrl = await setupLocalApiServer(user);
|
||||
const vercel = execCli(
|
||||
binaryPath,
|
||||
['domains', 'invalidSubCommand', '--api', loginApiUrl],
|
||||
{ env: { FORCE_TTY: '1' } }
|
||||
);
|
||||
const steps = loginSteps(vercel, user);
|
||||
await waitForPrompt(vercel, 'Please specify a valid subcommand');
|
||||
const output = await steps;
|
||||
expect(output.exitCode, formatOutput(output)).toBe(2);
|
||||
const config = await fs.readJSON(getGlobalConfigPath());
|
||||
expect(config.currentTeam).toEqual(user.defaultTeamId);
|
||||
});
|
||||
|
||||
it('should not allow setting user as scope', async () => {
|
||||
const loginApiUrl = await setupLocalApiServer(user);
|
||||
const vercel = execCli(
|
||||
binaryPath,
|
||||
[
|
||||
'domains',
|
||||
'invalidSubCommand',
|
||||
'--api',
|
||||
loginApiUrl,
|
||||
'--scope',
|
||||
user.username,
|
||||
],
|
||||
{ env: { FORCE_TTY: '1' } }
|
||||
);
|
||||
const steps = loginSteps(vercel, user);
|
||||
await waitForPrompt(
|
||||
vercel,
|
||||
'You cannot set your Personal Account as the scope.'
|
||||
);
|
||||
const output = await steps;
|
||||
expect(output.exitCode, formatOutput(output)).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
import { client } from '../../mocks/client';
|
||||
import domains from '../../../src/commands/domains';
|
||||
import { useUser } from '../../mocks/user';
|
||||
import { useDomains } from '../../mocks/domains';
|
||||
import { useTeams } from '../../mocks/team';
|
||||
import { useDomain, useDomains } from '../../mocks/domains';
|
||||
|
||||
describe('domains', () => {
|
||||
it('should list up to 20 domains by default', async () => {
|
||||
@@ -21,4 +22,19 @@ describe('domains', () => {
|
||||
await expect(client.stderr).toOutput('example-1.com');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should prevent moving a domain to a user account', async () => {
|
||||
const { username } = useUser({ version: 'northstar' });
|
||||
useTeams();
|
||||
useDomain('northstar');
|
||||
client.setArgv('domains', 'move', 'example-northstar.com', username);
|
||||
const exitCodePromise = domains(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Fetching domain example-northstar.com under ${username}
|
||||
Error: You may not move your domain to your user account.`
|
||||
);
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -426,5 +426,46 @@ describe('env', () => {
|
||||
);
|
||||
expect(gitignoreAfter).toBe(gitignoreBefore);
|
||||
});
|
||||
|
||||
it('should not pull VERCEL_ANALYTICS_ID', async () => {
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject(
|
||||
{
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
analytics: {
|
||||
id: 'VC-ANALYTICS-ID',
|
||||
enabledAt: Date.now(),
|
||||
},
|
||||
},
|
||||
[
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: '781dt89g8r2h789g',
|
||||
key: 'VERCEL_ANALYTICS_ID',
|
||||
value: 'VC-ANALYTICS-ID',
|
||||
target: ['development'],
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361455,
|
||||
createdAt: 1557241361455,
|
||||
},
|
||||
]
|
||||
);
|
||||
const cwd = setupUnitFixture('vercel-env-pull');
|
||||
client.cwd = cwd;
|
||||
client.setArgv('env', 'pull', '--yes');
|
||||
const exitCodePromise = env(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `development` Environment Variables for Project '
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env.local file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env.local'));
|
||||
|
||||
expect(rawDevEnv.toString().includes('VERCEL_ANALYTICS_ID')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,8 +13,8 @@ import { setupTmpDir } from '../../helpers/setup-unit-fixture';
|
||||
|
||||
describe('link', () => {
|
||||
it('should prompt for link', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
const user = useUser();
|
||||
const cwd = setupTmpDir();
|
||||
useTeams('team_dummy');
|
||||
const { project } = useProject({
|
||||
...defaultProject,
|
||||
|
||||
@@ -25,6 +25,22 @@ describe('login', () => {
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should set currentTeam to defaultTeamId', async () => {
|
||||
const user = useUser({
|
||||
version: 'northstar',
|
||||
defaultTeamId: 'northstar-defaultTeamId',
|
||||
});
|
||||
client.authConfig.token = undefined;
|
||||
client.setArgv('login', user.email);
|
||||
const exitCodePromise = login(client);
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
await expect(client.config.currentTeam).toEqual(
|
||||
'northstar-defaultTeamId'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('interactive', () => {
|
||||
it('should allow login via email', async () => {
|
||||
const user = useUser();
|
||||
|
||||
81
packages/cli/test/unit/commands/switch.test.ts
Normal file
81
packages/cli/test/unit/commands/switch.test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { client } from '../../mocks/client';
|
||||
import teamsSwitch from '../../../src/commands/teams/switch';
|
||||
import { useUser } from '../../mocks/user';
|
||||
import { useTeams } from '../../mocks/team';
|
||||
|
||||
describe('switch', () => {
|
||||
describe('non-northstar', () => {
|
||||
it('should let you switch to team and back', async () => {
|
||||
const user = useUser();
|
||||
const team = useTeams()[0];
|
||||
|
||||
// ? Switch to:
|
||||
// ── Personal Account ──────────────
|
||||
// ● Name (username) (current)
|
||||
// ── Teams ─────────────────────────
|
||||
// ○ Team (slug)
|
||||
// ──────────────────────────────────
|
||||
// ○ Cancel
|
||||
let exitCodePromise = teamsSwitch(client);
|
||||
await expect(client.stderr).toOutput('Switch to:');
|
||||
client.stdin.write('\x1B[B'); // Down arrow
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Success! The team ${team.name} (${team.slug}) is now active!`
|
||||
);
|
||||
|
||||
// ? Switch to:
|
||||
// ── Personal Account ──────────────
|
||||
// ○ Name (username)
|
||||
// ── Teams ─────────────────────────
|
||||
// ● Team (slug) (current)
|
||||
// ──────────────────────────────────
|
||||
// ○ Cancel
|
||||
exitCodePromise = teamsSwitch(client);
|
||||
await expect(client.stderr).toOutput('Switch to:');
|
||||
client.stdin.write('\x1B[A'); // Up arrow
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Your account (${user.username}) is now active!`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should not let you switch to personal account', async () => {
|
||||
const user = useUser({
|
||||
version: 'northstar',
|
||||
});
|
||||
const team = useTeams()[0];
|
||||
client.config.currentTeam = team.id;
|
||||
|
||||
// ? Switch to:
|
||||
// ── Teams ─────────────────────────
|
||||
// ● Team (slug) (current)
|
||||
// ──────────────────────────────────
|
||||
// ○ Cancel
|
||||
const exitCodePromise = teamsSwitch(client);
|
||||
// Test that personal account is not displayed in scope switcher
|
||||
await expect(client.stderr).not.toOutput(user.username);
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
await expect(client.stderr).toOutput('No changes made');
|
||||
});
|
||||
|
||||
it('should not let you switch to personal account if desiredSlug is set as personal account', async () => {
|
||||
const user = useUser({
|
||||
version: 'northstar',
|
||||
});
|
||||
useTeams();
|
||||
|
||||
const exitCodePromise = teamsSwitch(client, user.username);
|
||||
// Personal account should be hidden
|
||||
await expect(client.stderr).toOutput(
|
||||
'You cannot set your Personal Account as the scope.'
|
||||
);
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
30
packages/cli/test/unit/commands/teams.test.ts
Normal file
30
packages/cli/test/unit/commands/teams.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { client } from '../../mocks/client';
|
||||
import teamsList from '../../../src/commands/teams/list';
|
||||
import { useUser } from '../../mocks/user';
|
||||
import { useTeams } from '../../mocks/team';
|
||||
|
||||
describe('teams', () => {
|
||||
describe('ls', () => {
|
||||
describe('non-northstar', () => {
|
||||
it('should display your personal account', async () => {
|
||||
const user = useUser();
|
||||
useTeams(undefined, { apiVersion: 2 });
|
||||
const exitCodePromise = teamsList(client);
|
||||
await expect(client.stdout).toOutput(user.username);
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should not display your personal account', async () => {
|
||||
const user = useUser({
|
||||
version: 'northstar',
|
||||
});
|
||||
useTeams(undefined, { apiVersion: 2 });
|
||||
const exitCodePromise = teamsList(client);
|
||||
await expect(client.stdout).not.toOutput(user.username);
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
68
packages/cli/test/unit/util/get-scope.test.ts
Normal file
68
packages/cli/test/unit/util/get-scope.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { client } from '../../mocks/client';
|
||||
import { useUser } from '../../mocks/user';
|
||||
import { useTeams } from '../../mocks/team';
|
||||
import getScope from '../../../src/util/get-scope';
|
||||
|
||||
describe('getScope', () => {
|
||||
let mockTeam: ReturnType<typeof useTeams>[0];
|
||||
let mockUser: ReturnType<typeof useUser>;
|
||||
beforeEach(() => {
|
||||
mockTeam = useTeams()[0];
|
||||
});
|
||||
|
||||
describe('non-northstar', () => {
|
||||
beforeEach(() => {
|
||||
mockUser = useUser();
|
||||
});
|
||||
|
||||
it('should return user if team is unspecified', async () => {
|
||||
const { contextName, team, user } = await getScope(client);
|
||||
await expect(user.id).toEqual(mockUser.id);
|
||||
await expect(team).toBeNull();
|
||||
await expect(contextName).toEqual(mockUser.username);
|
||||
});
|
||||
|
||||
it('should return team if team is specified', async () => {
|
||||
client.config.currentTeam = mockTeam.id;
|
||||
const { contextName, team, user } = await getScope(client);
|
||||
await expect(user.id).toEqual(mockUser.id);
|
||||
await expect(team?.id).toEqual(mockTeam.id);
|
||||
await expect(contextName).toEqual(mockTeam.slug);
|
||||
});
|
||||
|
||||
it('should not return team if team is specified but getTeam is false', async () => {
|
||||
client.config.currentTeam = mockTeam.id;
|
||||
const { contextName, team, user } = await getScope(client, {
|
||||
getTeam: false,
|
||||
});
|
||||
await expect(user.id).toEqual(mockUser.id);
|
||||
await expect(team).toBeNull();
|
||||
await expect(contextName).toEqual(mockUser.username);
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
beforeEach(() => {
|
||||
mockUser = useUser({
|
||||
version: 'northstar',
|
||||
defaultTeamId: mockTeam.id,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return default team', async () => {
|
||||
const { contextName, team, user } = await getScope(client);
|
||||
await expect(user.id).toEqual(mockUser.id);
|
||||
await expect(team?.id).toEqual(mockTeam.id);
|
||||
await expect(contextName).toEqual(mockTeam.slug);
|
||||
});
|
||||
|
||||
it('should not return default team if getTeam is false', async () => {
|
||||
const { contextName, team, user } = await getScope(client, {
|
||||
getTeam: false,
|
||||
});
|
||||
await expect(user.id).toEqual(mockUser.id);
|
||||
await expect(team).toBeNull();
|
||||
await expect(contextName).toEqual(mockUser.username);
|
||||
});
|
||||
});
|
||||
});
|
||||
40
packages/cli/test/unit/util/input/select-org.test.ts
Normal file
40
packages/cli/test/unit/util/input/select-org.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { client } from '../../../mocks/client';
|
||||
import selectOrg from '../../../../src/util/input/select-org';
|
||||
import { useTeams } from '../../../mocks/team';
|
||||
import { useUser } from '../../../mocks/user';
|
||||
|
||||
describe('selectOrg', () => {
|
||||
describe('non-northstar', () => {
|
||||
it('should allow selecting user', async () => {
|
||||
const user = useUser();
|
||||
useTeams();
|
||||
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||
await expect(client.stderr).toOutput(user.name);
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(selectOrgPromise).resolves.toHaveProperty('id', user.id);
|
||||
});
|
||||
|
||||
it('should allow selecting team', async () => {
|
||||
useUser();
|
||||
const team = useTeams()[0];
|
||||
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||
await expect(client.stderr).toOutput('Select the scope');
|
||||
client.stdin.write('\x1B[B'); // Down arrow
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should not allow selecting user', async () => {
|
||||
const user = useUser({
|
||||
version: 'northstar',
|
||||
});
|
||||
const team = useTeams()[0];
|
||||
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||
await expect(client.stderr).not.toOutput(user.name);
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { client } from '../../../mocks/client';
|
||||
import { useUser } from '../../../mocks/user';
|
||||
import { updateCurrentTeamAfterLogin } from '../../../../src/util/login/update-current-team-after-login';
|
||||
|
||||
describe('updateCurrentTeamAfterLogin', () => {
|
||||
describe('SSO Login', () => {
|
||||
it('should set currentTeam to SSO team ID', async () => {
|
||||
useUser();
|
||||
await updateCurrentTeamAfterLogin(client, client.output, 'ssoTeamId');
|
||||
await expect(client.config.currentTeam).toEqual('ssoTeamId');
|
||||
});
|
||||
});
|
||||
|
||||
describe('northstar', () => {
|
||||
it('should set currentTeam to defaultTeamId', async () => {
|
||||
useUser({
|
||||
version: 'northstar',
|
||||
defaultTeamId: 'defaultTeamId',
|
||||
});
|
||||
await updateCurrentTeamAfterLogin(client, client.output);
|
||||
await expect(client.config.currentTeam).toEqual('defaultTeamId');
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-northstar', () => {
|
||||
it('should reset currentTeam', async () => {
|
||||
client.config.currentTeam = 'previousTeamId';
|
||||
useUser();
|
||||
await updateCurrentTeamAfterLogin(client, client.output);
|
||||
await expect(client.config.currentTeam).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,12 @@
|
||||
# @vercel/client
|
||||
|
||||
## 13.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||
- @vercel/build-utils@7.2.1
|
||||
|
||||
## 13.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "13.0.3",
|
||||
"version": "13.0.4",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -36,7 +36,7 @@
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/routing-utils": "3.0.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @vercel/edge
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Add flag to geolocation ([#10443](https://github.com/vercel/vercel/pull/10443))
|
||||
|
||||
Usage
|
||||
|
||||
```
|
||||
const { flag } = geolocation(req)
|
||||
```
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
- [CITY_HEADER_NAME](README.md#city_header_name)
|
||||
- [COUNTRY_HEADER_NAME](README.md#country_header_name)
|
||||
- [EMOJI_FLAG_UNICODE_STARTING_POSITION](README.md#emoji_flag_unicode_starting_position)
|
||||
- [IP_HEADER_NAME](README.md#ip_header_name)
|
||||
- [LATITUDE_HEADER_NAME](README.md#latitude_header_name)
|
||||
- [LONGITUDE_HEADER_NAME](README.md#longitude_header_name)
|
||||
@@ -53,6 +54,18 @@ Country of the original client IP as calculated by Vercel Proxy.
|
||||
|
||||
---
|
||||
|
||||
### EMOJI_FLAG_UNICODE_STARTING_POSITION
|
||||
|
||||
• `Const` **EMOJI_FLAG_UNICODE_STARTING_POSITION**: `127397`
|
||||
|
||||
Unicode characters for emoji flags start at this number, and run up to 127469.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:34](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L34)
|
||||
|
||||
---
|
||||
|
||||
### IP_HEADER_NAME
|
||||
|
||||
• `Const` **IP_HEADER_NAME**: `"x-real-ip"`
|
||||
@@ -141,7 +154,7 @@ Returns the location information for the incoming request.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:106](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L106)
|
||||
[packages/edge/src/edge-headers.ts:128](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L128)
|
||||
|
||||
---
|
||||
|
||||
@@ -167,7 +180,7 @@ Returns the IP address of the request from the headers.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:77](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L77)
|
||||
[packages/edge/src/edge-headers.ts:99](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L99)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ The location information of a given request.
|
||||
- [city](Geo.md#city)
|
||||
- [country](Geo.md#country)
|
||||
- [countryRegion](Geo.md#countryregion)
|
||||
- [flag](Geo.md#flag)
|
||||
- [latitude](Geo.md#latitude)
|
||||
- [longitude](Geo.md#longitude)
|
||||
- [region](Geo.md#region)
|
||||
@@ -23,7 +24,7 @@ The city that the request originated from.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:47](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L47)
|
||||
[packages/edge/src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
|
||||
|
||||
---
|
||||
|
||||
@@ -35,7 +36,7 @@ The country that the request originated from.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
|
||||
[packages/edge/src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)
|
||||
|
||||
---
|
||||
|
||||
@@ -48,7 +49,19 @@ See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-cou
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:58](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L58)
|
||||
[packages/edge/src/edge-headers.ts:64](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L64)
|
||||
|
||||
---
|
||||
|
||||
### flag
|
||||
|
||||
• `Optional` **flag**: `string`
|
||||
|
||||
The flag emoji for the country the request originated from.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:56](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L56)
|
||||
|
||||
---
|
||||
|
||||
@@ -60,7 +73,7 @@ The latitude of the client.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:61](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L61)
|
||||
[packages/edge/src/edge-headers.ts:67](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L67)
|
||||
|
||||
---
|
||||
|
||||
@@ -72,7 +85,7 @@ The longitude of the client.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:64](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L64)
|
||||
[packages/edge/src/edge-headers.ts:70](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L70)
|
||||
|
||||
---
|
||||
|
||||
@@ -84,4 +97,4 @@ The [Vercel Edge Network region](https://vercel.com/docs/concepts/edge-network/r
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/edge/src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)
|
||||
[packages/edge/src/edge-headers.ts:59](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L59)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/edge",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"license": "Apache-2.0",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
|
||||
@@ -28,7 +28,10 @@ export const REGION_HEADER_NAME = 'x-vercel-ip-country-region';
|
||||
* The request ID for each request generated by Vercel Proxy.
|
||||
*/
|
||||
export const REQUEST_ID_HEADER_NAME = 'x-vercel-id';
|
||||
|
||||
/**
|
||||
* Unicode characters for emoji flags start at this number, and run up to 127469.
|
||||
*/
|
||||
export const EMOJI_FLAG_UNICODE_STARTING_POSITION = 127397;
|
||||
/**
|
||||
* We define a new type so this function can be reused with
|
||||
* the global `Request`, `node-fetch` and other types.
|
||||
@@ -49,6 +52,9 @@ export interface Geo {
|
||||
/** The country that the request originated from. */
|
||||
country?: string;
|
||||
|
||||
/** The flag emoji for the country the request originated from. */
|
||||
flag?: string;
|
||||
|
||||
/** The [Vercel Edge Network region](https://vercel.com/docs/concepts/edge-network/regions) that received the request. */
|
||||
region?: string;
|
||||
|
||||
@@ -68,6 +74,22 @@ function getHeader(request: Request, key: string): string | undefined {
|
||||
return request.headers.get(key) ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the 2 digit countryCode into a flag emoji by adding the current character value to the emoji flag unicode starting position. See [Country Code to Flag Emoji](https://dev.to/jorik/country-code-to-flag-emoji-a21) by Jorik Tangelder.
|
||||
*
|
||||
* @param countryCode The country code returned by: `getHeader(request, COUNTRY_HEADER_NAME)`.
|
||||
* @returns A flag emoji or undefined.
|
||||
*/
|
||||
function getFlag(countryCode: string | undefined): string | undefined {
|
||||
const regex = new RegExp('^[A-Z]{2}$').test(countryCode!);
|
||||
if (!countryCode || !regex) return undefined;
|
||||
return String.fromCodePoint(
|
||||
...countryCode
|
||||
.split('')
|
||||
.map(char => EMOJI_FLAG_UNICODE_STARTING_POSITION + char.charCodeAt(0))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP address of the request from the headers.
|
||||
*
|
||||
@@ -107,6 +129,7 @@ export function geolocation(request: Request): Geo {
|
||||
return {
|
||||
city: getHeader(request, CITY_HEADER_NAME),
|
||||
country: getHeader(request, COUNTRY_HEADER_NAME),
|
||||
flag: getFlag(getHeader(request, COUNTRY_HEADER_NAME)),
|
||||
countryRegion: getHeader(request, REGION_HEADER_NAME),
|
||||
region: getRegionFromRequestId(getHeader(request, REQUEST_ID_HEADER_NAME)),
|
||||
latitude: getHeader(request, LATITUDE_HEADER_NAME),
|
||||
|
||||
37
packages/edge/test/edge-headers.test.ts
vendored
37
packages/edge/test/edge-headers.test.ts
vendored
@@ -29,6 +29,7 @@ describe('`geolocation`', () => {
|
||||
const req = new Request('https://example.vercel.sh');
|
||||
expect(geolocation(req)).toEqual({
|
||||
city: undefined,
|
||||
flag: undefined,
|
||||
country: undefined,
|
||||
countryRegion: undefined,
|
||||
latitude: undefined,
|
||||
@@ -41,7 +42,7 @@ describe('`geolocation`', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[CITY_HEADER_NAME]: 'Tel Aviv',
|
||||
[COUNTRY_HEADER_NAME]: 'Israel',
|
||||
[COUNTRY_HEADER_NAME]: 'IL',
|
||||
[LATITUDE_HEADER_NAME]: '32.109333',
|
||||
[LONGITUDE_HEADER_NAME]: '34.855499',
|
||||
[REGION_HEADER_NAME]: 'TA', // https://en.wikipedia.org/wiki/ISO_3166-2:IL
|
||||
@@ -50,7 +51,8 @@ describe('`geolocation`', () => {
|
||||
});
|
||||
expect(geolocation(req)).toEqual<Geo>({
|
||||
city: 'Tel Aviv',
|
||||
country: 'Israel',
|
||||
flag: '🇮🇱',
|
||||
country: 'IL',
|
||||
latitude: '32.109333',
|
||||
longitude: '34.855499',
|
||||
region: 'fra1',
|
||||
@@ -62,7 +64,7 @@ describe('`geolocation`', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[CITY_HEADER_NAME]: 'Tokyo',
|
||||
[COUNTRY_HEADER_NAME]: 'Japan',
|
||||
[COUNTRY_HEADER_NAME]: 'JP',
|
||||
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||
[REGION_HEADER_NAME]: '13',
|
||||
@@ -71,7 +73,8 @@ describe('`geolocation`', () => {
|
||||
});
|
||||
expect(geolocation(req)).toEqual<Geo>({
|
||||
city: 'Tokyo',
|
||||
country: 'Japan',
|
||||
flag: '🇯🇵',
|
||||
country: 'JP',
|
||||
latitude: '37.1233',
|
||||
longitude: '30.733399',
|
||||
region: 'hnd1',
|
||||
@@ -83,7 +86,7 @@ describe('`geolocation`', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[CITY_HEADER_NAME]: 'Tokyo',
|
||||
[COUNTRY_HEADER_NAME]: 'Japan',
|
||||
[COUNTRY_HEADER_NAME]: 'JP',
|
||||
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||
[REGION_HEADER_NAME]: '13',
|
||||
@@ -91,7 +94,29 @@ describe('`geolocation`', () => {
|
||||
});
|
||||
expect(geolocation(req)).toEqual<Geo>({
|
||||
city: 'Tokyo',
|
||||
country: 'Japan',
|
||||
flag: '🇯🇵',
|
||||
country: 'JP',
|
||||
latitude: '37.1233',
|
||||
longitude: '30.733399',
|
||||
region: 'dev1',
|
||||
countryRegion: '13',
|
||||
});
|
||||
});
|
||||
|
||||
test('returns undefined if countryCode is invalid', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[CITY_HEADER_NAME]: 'Tokyo',
|
||||
[COUNTRY_HEADER_NAME]: 'AAA',
|
||||
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||
[REGION_HEADER_NAME]: '13',
|
||||
},
|
||||
});
|
||||
expect(geolocation(req)).toEqual<Geo>({
|
||||
city: 'Tokyo',
|
||||
flag: undefined,
|
||||
country: 'AAA',
|
||||
latitude: '37.1233',
|
||||
longitude: '30.733399',
|
||||
region: 'dev1',
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"@types/minimatch": "3.0.5",
|
||||
"@types/node": "14.18.33",
|
||||
"@types/semver": "7.3.10",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"jest-junit": "16.0.0",
|
||||
"typescript": "4.9.5"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
gatsby-browser.js
|
||||
web-vitals.js
|
||||
|
||||
7
packages/gatsby-plugin-vercel-analytics/CHANGELOG.md
Normal file
7
packages/gatsby-plugin-vercel-analytics/CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# @vercel/gatsby-plugin-vercel-analytics
|
||||
|
||||
## 1.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Remove "babel" compilation ([#10546](https://github.com/vercel/vercel/pull/10546))
|
||||
@@ -1,17 +1,13 @@
|
||||
{
|
||||
"name": "@vercel/gatsby-plugin-vercel-analytics",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.11",
|
||||
"description": "Track Core Web Vitals in Gatsby projects with Vercel Speed Insights.",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"gatsby-browser.js",
|
||||
"web-vitals.js"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "babel src --out-dir ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.12.1",
|
||||
"web-vitals": "0.2.4"
|
||||
},
|
||||
"repository": {
|
||||
@@ -33,8 +29,6 @@
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.20.7",
|
||||
"@babel/core": "7.5.0",
|
||||
"jest-junit": "16.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
gatsby-node.*
|
||||
!gatsby-node.ts
|
||||
|
||||
dist
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @vercel/gatsby-plugin-vercel-builder
|
||||
|
||||
## 2.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Use "esbuild" to build package ([#10508](https://github.com/vercel/vercel/pull/10508))
|
||||
|
||||
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||
- @vercel/build-utils@7.2.1
|
||||
|
||||
## 2.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
8
packages/gatsby-plugin-vercel-builder/gatsby-node.js
Normal file
8
packages/gatsby-plugin-vercel-builder/gatsby-node.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const { generateVercelBuildOutputAPI3Output } = require('./dist/index.js');
|
||||
|
||||
exports.onPostBuild = async ({ store }) => {
|
||||
await generateVercelBuildOutputAPI3Output({
|
||||
// validated by `pluginOptionSchema`
|
||||
gatsbyStoreState: store.getState(),
|
||||
});
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
// this gets built separately, so import from "dist" instead of "src"
|
||||
import { generateVercelBuildOutputAPI3Output } from './dist';
|
||||
|
||||
export const onPostBuild = async ({ store }: { store: any }) => {
|
||||
await generateVercelBuildOutputAPI3Output({
|
||||
// validated by `pluginOptionSchema`
|
||||
gatsbyStoreState: store.getState(),
|
||||
});
|
||||
};
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "@vercel/gatsby-plugin-vercel-builder",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.6",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist",
|
||||
"gatsby-node.ts",
|
||||
"gatsby-node.js",
|
||||
"gatsby-node.js.map"
|
||||
"templates",
|
||||
"gatsby-node.js"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -14,14 +13,11 @@
|
||||
"directory": "packages/gatsby-plugin-vercel-builder"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm build:src && pnpm build:gatsby",
|
||||
"build:gatsby": "tsc -p tsconfig.gatsby.json",
|
||||
"build:src": "tsc -p tsconfig.src.json"
|
||||
"build": "node ../../utils/build-builder.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sinclair/typebox": "0.25.24",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/node": "3.0.5",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/routing-utils": "3.0.0",
|
||||
"esbuild": "0.14.47",
|
||||
"etag": "1.8.1",
|
||||
|
||||
@@ -24,7 +24,7 @@ export const writeHandler = async ({
|
||||
const { major } = await getNodeVersion(process.cwd());
|
||||
|
||||
try {
|
||||
return await build({
|
||||
await build({
|
||||
entryPoints: [handlerFile],
|
||||
loader: { '.ts': 'ts' },
|
||||
outfile: join(outDir, 'index.js'),
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import os from 'os';
|
||||
|
||||
const TMP_DATA_PATH = join(os.tmpdir(), 'data/datastore');
|
||||
|
||||
export async function getGraphQLEngine() {
|
||||
const { GraphQLEngine } = await import(
|
||||
join(__dirname, '.cache/query-engine/index.js')
|
||||
);
|
||||
|
||||
return new GraphQLEngine({ dbPath: TMP_DATA_PATH });
|
||||
}
|
||||
|
||||
export async function getPageSSRHelpers() {
|
||||
return await import(join(__dirname, '.cache/page-ssr/index.js'));
|
||||
}
|
||||
@@ -21,7 +21,7 @@ export async function createServerlessFunctions(
|
||||
) {
|
||||
let functionName: string;
|
||||
let functionDir: string;
|
||||
const handlerFile = join(__dirname, '../handlers/templates/ssr-handler.js');
|
||||
const handlerFile = join(__dirname, '../templates/ssr-handler.js');
|
||||
|
||||
await Promise.all(
|
||||
ssrRoutes.map(async (page, index) => {
|
||||
|
||||
@@ -3,8 +3,6 @@ import etag from 'etag';
|
||||
import { parse } from 'url';
|
||||
import { copySync, existsSync } from 'fs-extra';
|
||||
import { join, dirname, basename } from 'path';
|
||||
import { getPageSSRHelpers, getGraphQLEngine } from '../utils';
|
||||
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
||||
|
||||
const TMP_DATA_PATH = join(os.tmpdir(), 'data/datastore');
|
||||
const CUR_DATA_PATH = join(__dirname, '.cache/data/datastore');
|
||||
@@ -14,9 +12,21 @@ if (!existsSync(TMP_DATA_PATH)) {
|
||||
copySync(CUR_DATA_PATH, TMP_DATA_PATH);
|
||||
}
|
||||
|
||||
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
||||
let pageName: string;
|
||||
const pathname = parse(req.url!).pathname || '/';
|
||||
async function getGraphQLEngine() {
|
||||
const { GraphQLEngine } = await import(
|
||||
join(__dirname, '.cache/query-engine/index.js')
|
||||
);
|
||||
|
||||
return new GraphQLEngine({ dbPath: TMP_DATA_PATH });
|
||||
}
|
||||
|
||||
async function getPageSSRHelpers() {
|
||||
return await import(join(__dirname, '.cache/page-ssr/index.js'));
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
let pageName;
|
||||
const pathname = parse(req.url).pathname || '/';
|
||||
const isPageData = pathname.startsWith('/page-data/');
|
||||
if (isPageData) {
|
||||
// /page-data/index/page-data.json
|
||||
@@ -53,7 +63,7 @@ export default async function handler(req: VercelRequest, res: VercelResponse) {
|
||||
|
||||
if (data.serverDataHeaders) {
|
||||
for (const [name, value] of Object.entries(data.serverDataHeaders)) {
|
||||
res.setHeader(name, value as string);
|
||||
res.setHeader(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||
"declarationMap": true /* Create sourcemaps for d.ts files. */,
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": []
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"declarationMap": false
|
||||
},
|
||||
"include": ["gatsby-node.ts"]
|
||||
}
|
||||
20
packages/gatsby-plugin-vercel-builder/tsconfig.json
Normal file
20
packages/gatsby-plugin-vercel-builder/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ES2021"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"outDir": "./dist",
|
||||
"types": ["node", "jest"],
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "ES2021"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"$schema": "https://turborepo.org/schema.json",
|
||||
"extends": ["//"],
|
||||
"pipeline": {
|
||||
"build": {
|
||||
"outputs": ["dist/**", "gatsby-node.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
# @vercel/go
|
||||
|
||||
## 3.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add support for Go v1.21.0 ([#10552](https://github.com/vercel/vercel/pull/10552))
|
||||
|
||||
## 3.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@types/node-fetch": "^2.3.0",
|
||||
"@types/tar": "6.1.5",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.3",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -22,6 +22,7 @@ import type { Env } from '@vercel/build-utils';
|
||||
const streamPipeline = promisify(pipeline);
|
||||
|
||||
const versionMap = new Map([
|
||||
['1.21', '1.21.1'],
|
||||
['1.20', '1.20.2'],
|
||||
['1.19', '1.19.6'],
|
||||
['1.18', '1.18.10'],
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
{ "src": "subdirectory/index.go", "use": "@vercel/go" }
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "cow:go1.20.2:RANDOMNESS_PLACEHOLDER" },
|
||||
{ "path": "/", "mustContain": "cow:go1.21.1:RANDOMNESS_PLACEHOLDER" },
|
||||
{
|
||||
"path": "/subdirectory",
|
||||
"mustContain": "subcow:go1.20.2:RANDOMNESS_PLACEHOLDER"
|
||||
"mustContain": "subcow:go1.21.1:RANDOMNESS_PLACEHOLDER"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "14.18.33",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"execa": "3.2.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"jest-junit": "16.0.0"
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @vercel/next
|
||||
|
||||
## 4.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
|
||||
|
||||
- Update `@vercel/nft` to v0.24.1. ([#10540](https://github.com/vercel/vercel/pull/10540))
|
||||
|
||||
- Build package using "esbuild" ([#10482](https://github.com/vercel/vercel/pull/10482))
|
||||
|
||||
## 4.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix feature flag detection ([#10531](https://github.com/vercel/vercel/pull/10531))
|
||||
|
||||
## 4.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
const execa = require('execa');
|
||||
const { remove, rename } = require('fs-extra');
|
||||
const buildEdgeFunctionTemplate = require('./scripts/build-edge-function-template');
|
||||
|
||||
async function main() {
|
||||
const isDevBuild = process.argv.includes('--dev');
|
||||
|
||||
await remove('dist');
|
||||
await execa('tsc', [], { stdio: 'inherit' });
|
||||
await buildEdgeFunctionTemplate();
|
||||
|
||||
if (!isDevBuild) {
|
||||
await execa(
|
||||
'ncc',
|
||||
[
|
||||
'build',
|
||||
'src/index.ts',
|
||||
'--minify',
|
||||
'-e',
|
||||
'esbuild',
|
||||
'-e',
|
||||
'@vercel/build-utils',
|
||||
'-o',
|
||||
'dist/main',
|
||||
],
|
||||
{ stdio: 'inherit' }
|
||||
);
|
||||
await rename('dist/main/index.js', 'dist/index.js');
|
||||
await remove('dist/main');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
26
packages/next/build.mjs
Normal file
26
packages/next/build.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
import { join } from 'node:path';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { esbuild } from '../../utils/build.mjs';
|
||||
import buildEdgeFunctionTemplate from './scripts/build-edge-function-template.js';
|
||||
|
||||
const pkgPath = join(process.cwd(), 'package.json');
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
||||
const externals = Object.keys(pkg.dependencies || {});
|
||||
|
||||
await Promise.all([
|
||||
// Compile all launcher `.ts` files into the "dist" dir
|
||||
esbuild({
|
||||
entryPoints: [
|
||||
'src/legacy-launcher.ts',
|
||||
'src/server-launcher.ts',
|
||||
'src/templated-launcher-shared.ts',
|
||||
'src/templated-launcher.ts',
|
||||
],
|
||||
}),
|
||||
buildEdgeFunctionTemplate(),
|
||||
]);
|
||||
|
||||
await esbuild({
|
||||
bundle: true,
|
||||
external: ['@vercel/build-utils', ...externals],
|
||||
});
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "4.0.5",
|
||||
"version": "4.0.7",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
"scripts": {
|
||||
"build": "node build.js",
|
||||
"build-dev": "node build.js --dev",
|
||||
"build": "node build.mjs",
|
||||
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail --runInBand --testTimeout=360000",
|
||||
"test-unit": "pnpm test test/unit/",
|
||||
"test-next-local": "pnpm test test/integration/*.test.js test/integration/*.test.ts",
|
||||
@@ -21,6 +20,9 @@
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/buffer-crc32": "0.2.0",
|
||||
@@ -29,14 +31,14 @@
|
||||
"@types/find-up": "4.0.0",
|
||||
"@types/fs-extra": "8.0.0",
|
||||
"@types/glob": "7.1.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/next-server": "8.0.0",
|
||||
"@types/node": "14.18.33",
|
||||
"@types/resolve-from": "5.0.1",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "7.2.0",
|
||||
"@vercel/nft": "0.22.5",
|
||||
"@vercel/build-utils": "7.2.1",
|
||||
"@vercel/routing-utils": "3.0.0",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
|
||||
14
packages/next/src/constants.ts
Normal file
14
packages/next/src/constants.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export const KIB = 1024;
|
||||
|
||||
export const MIB = 1024 * KIB;
|
||||
|
||||
/**
|
||||
* The maximum size of a *compressed* edge function.
|
||||
*/
|
||||
export const EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
|
||||
|
||||
export const MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
|
||||
|
||||
export const LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * MIB;
|
||||
|
||||
export const LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * KIB;
|
||||
@@ -1,6 +0,0 @@
|
||||
import { MIB } from '../utils';
|
||||
|
||||
/**
|
||||
* The maximum size of a *compressed* edge function.
|
||||
*/
|
||||
export const EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
|
||||
@@ -3,10 +3,10 @@ import { readFile } from 'fs-extra';
|
||||
import { ConcatSource, Source } from 'webpack-sources';
|
||||
import { fileToSource, raw, sourcemapped } from '../sourcemapped';
|
||||
import { join } from 'path';
|
||||
import { EDGE_FUNCTION_SIZE_LIMIT } from './constants';
|
||||
import { EDGE_FUNCTION_SIZE_LIMIT } from '../constants';
|
||||
import zlib from 'zlib';
|
||||
import { promisify } from 'util';
|
||||
import { prettyBytes } from '../utils';
|
||||
import { prettyBytes } from '../pretty-bytes';
|
||||
|
||||
// @ts-ignore this is a prebuilt file, based on `../../scripts/build-edge-function-template.js`
|
||||
import template from '../../dist/___get-nextjs-edge-function.js';
|
||||
|
||||
@@ -46,14 +46,13 @@ import {
|
||||
writeFile,
|
||||
} from 'fs-extra';
|
||||
import path from 'path';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import semver from 'semver';
|
||||
import url from 'url';
|
||||
import createServerlessConfig from './create-serverless-config';
|
||||
import nextLegacyVersions from './legacy-versions';
|
||||
import { serverBuild } from './server-build';
|
||||
import { MIB } from './constants';
|
||||
import {
|
||||
MIB,
|
||||
collectTracedFiles,
|
||||
createLambdaFromPseudoLayers,
|
||||
createPseudoLayer,
|
||||
@@ -76,6 +75,7 @@ import {
|
||||
getRoutesManifest,
|
||||
getSourceFilePathFromPage,
|
||||
getStaticFiles,
|
||||
getVariantsManifest,
|
||||
isDynamicRoute,
|
||||
localizeDynamicRoutes,
|
||||
normalizeIndexOutput,
|
||||
@@ -92,6 +92,7 @@ import {
|
||||
isApiPage,
|
||||
getFunctionsConfigManifest,
|
||||
normalizeEdgeFunctionPath,
|
||||
require_,
|
||||
} from './utils';
|
||||
|
||||
export const version = 2;
|
||||
@@ -147,10 +148,10 @@ function getRealNextVersion(entryPath: string): string | false {
|
||||
// package.json. This allows the builder to be used with frameworks like Blitz that
|
||||
// bundle Next but where Next isn't in the project root's package.json
|
||||
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
const nextVersion: string = eval('require')(
|
||||
resolveFrom(entryPath, 'next/package.json')
|
||||
).version;
|
||||
const resolved = require_.resolve('next/package.json', {
|
||||
paths: [entryPath],
|
||||
});
|
||||
const nextVersion: string = require_(resolved).version;
|
||||
console.log(`Detected Next.js version: ${nextVersion}`);
|
||||
return nextVersion;
|
||||
} catch (_ignored) {
|
||||
@@ -496,6 +497,11 @@ export const build: BuildV2 = async ({
|
||||
outputDirectory
|
||||
);
|
||||
|
||||
const variantsManifest = await getVariantsManifest(
|
||||
entryPath,
|
||||
outputDirectory
|
||||
);
|
||||
|
||||
const routesManifest = await getRoutesManifest(
|
||||
entryPath,
|
||||
outputDirectory,
|
||||
@@ -1365,6 +1371,7 @@ export const build: BuildV2 = async ({
|
||||
privateOutputs,
|
||||
hasIsr404Page,
|
||||
hasIsr500Page,
|
||||
variantsManifest,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1927,8 +1934,8 @@ export const build: BuildV2 = async ({
|
||||
const groupPageKeys = Object.keys(group.pages);
|
||||
|
||||
const launcher = launcherData.replace(
|
||||
/\/\/ __LAUNCHER_PAGE_HANDLER__/g,
|
||||
`
|
||||
'let page = {};',
|
||||
`let page = {};
|
||||
const url = require('url');
|
||||
|
||||
${
|
||||
|
||||
3
packages/next/src/pretty-bytes.ts
Normal file
3
packages/next/src/pretty-bytes.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import bytes from 'bytes';
|
||||
|
||||
export const prettyBytes = (n: number) => bytes(n, { unitSeparator: ' ' });
|
||||
@@ -12,10 +12,12 @@ import {
|
||||
debug,
|
||||
glob,
|
||||
Files,
|
||||
Flag,
|
||||
BuildResultV2Typical as BuildResult,
|
||||
} from '@vercel/build-utils';
|
||||
import { Route, RouteWithHandle } from '@vercel/routing-utils';
|
||||
import { MAX_AGE_ONE_YEAR } from '.';
|
||||
import { MAX_UNCOMPRESSED_LAMBDA_SIZE } from './constants';
|
||||
import {
|
||||
NextRequiredServerFilesManifest,
|
||||
NextImagesManifest,
|
||||
@@ -36,7 +38,6 @@ import {
|
||||
PseudoFile,
|
||||
detectLambdaLimitExceeding,
|
||||
outputFunctionFileSizeInfo,
|
||||
MAX_UNCOMPRESSED_LAMBDA_SIZE,
|
||||
normalizeIndexOutput,
|
||||
getImagesConfig,
|
||||
getNextServerPath,
|
||||
@@ -45,6 +46,7 @@ import {
|
||||
UnwrapPromise,
|
||||
getOperationType,
|
||||
FunctionsConfigManifestV1,
|
||||
VariantsManifest,
|
||||
RSC_CONTENT_TYPE,
|
||||
RSC_PREFETCH_SUFFIX,
|
||||
} from './utils';
|
||||
@@ -111,6 +113,7 @@ export async function serverBuild({
|
||||
isCorrectLocaleAPIRoutes,
|
||||
lambdaCompressedByteLimit,
|
||||
requiredServerFilesManifest,
|
||||
variantsManifest,
|
||||
}: {
|
||||
appPathRoutesManifest?: Record<string, string>;
|
||||
dynamicPages: string[];
|
||||
@@ -151,6 +154,7 @@ export async function serverBuild({
|
||||
imagesManifest?: NextImagesManifest;
|
||||
prerenderManifest: NextPrerenderedRoutes;
|
||||
requiredServerFilesManifest: NextRequiredServerFilesManifest;
|
||||
variantsManifest: VariantsManifest | null;
|
||||
}): Promise<BuildResult> {
|
||||
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
|
||||
|
||||
@@ -313,7 +317,7 @@ export async function serverBuild({
|
||||
|
||||
const useBundledServer =
|
||||
semver.gte(nextVersion, BUNDLED_SERVER_NEXT_VERSION) &&
|
||||
process.env.VERCEL_NEXT_BUNDLED_SERVER;
|
||||
process.env.VERCEL_NEXT_BUNDLED_SERVER === '1';
|
||||
|
||||
if (useBundledServer) {
|
||||
debug('Using bundled Next.js server');
|
||||
@@ -1345,6 +1349,14 @@ export async function serverBuild({
|
||||
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
|
||||
const appNotFoundPath = path.posix.join('.', entryDirectory, '_not-found');
|
||||
|
||||
const flags: Flag[] = variantsManifest
|
||||
? Object.entries(variantsManifest).map(([key, value]) => ({
|
||||
key,
|
||||
...value,
|
||||
metadata: value.metadata ?? {},
|
||||
}))
|
||||
: [];
|
||||
|
||||
return {
|
||||
wildcard: wildcardConfig,
|
||||
images: getImagesConfig(imagesManifest),
|
||||
@@ -2046,5 +2058,6 @@ export async function serverBuild({
|
||||
]),
|
||||
],
|
||||
framework: { version: nextVersion },
|
||||
flags,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import { Sema } from 'async-sema';
|
||||
import crc32 from 'buffer-crc32';
|
||||
import fs, { lstat, stat } from 'fs-extra';
|
||||
import path from 'path';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import semver from 'semver';
|
||||
import zlib from 'zlib';
|
||||
import url from 'url';
|
||||
import { createRequire } from 'module';
|
||||
import escapeStringRegexp from 'escape-string-regexp';
|
||||
import { htmlContentType } from '.';
|
||||
import textTable from 'text-table';
|
||||
@@ -39,14 +39,18 @@ import { getNextjsEdgeFunctionSource } from './edge-function-source/get-edge-fun
|
||||
import type { LambdaOptionsWithFiles } from '@vercel/build-utils/dist/lambda';
|
||||
import { stringifySourceMap } from './sourcemapped';
|
||||
import type { RawSourceMap } from 'source-map';
|
||||
import bytes from 'bytes';
|
||||
import { prettyBytes } from './pretty-bytes';
|
||||
import {
|
||||
MIB,
|
||||
KIB,
|
||||
MAX_UNCOMPRESSED_LAMBDA_SIZE,
|
||||
LAMBDA_RESERVED_COMPRESSED_SIZE,
|
||||
LAMBDA_RESERVED_UNCOMPRESSED_SIZE,
|
||||
} from './constants';
|
||||
|
||||
type stringMap = { [key: string]: string };
|
||||
|
||||
export const KIB = 1024;
|
||||
export const MIB = 1024 * KIB;
|
||||
|
||||
export const prettyBytes = (n: number) => bytes(n, { unitSeparator: ' ' });
|
||||
export const require_ = createRequire(__filename);
|
||||
|
||||
export const RSC_CONTENT_TYPE = 'x-component';
|
||||
export const RSC_PREFETCH_SUFFIX = '.prefetch.rsc';
|
||||
@@ -420,10 +424,10 @@ export async function getDynamicRoutes(
|
||||
let getSortedRoutes: ((normalizedPages: string[]) => string[]) | undefined;
|
||||
|
||||
try {
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
({ getRouteRegex, getSortedRoutes } = eval('require')(
|
||||
resolveFrom(entryPath, 'next-server/dist/lib/router/utils')
|
||||
));
|
||||
const resolved = require_.resolve('next-server/dist/lib/router/utils', {
|
||||
paths: [entryPath],
|
||||
});
|
||||
({ getRouteRegex, getSortedRoutes } = require_(resolved));
|
||||
if (typeof getRouteRegex !== 'function') {
|
||||
getRouteRegex = undefined;
|
||||
}
|
||||
@@ -431,10 +435,11 @@ export async function getDynamicRoutes(
|
||||
|
||||
if (!getRouteRegex || !getSortedRoutes) {
|
||||
try {
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
({ getRouteRegex, getSortedRoutes } = eval('require')(
|
||||
resolveFrom(entryPath, 'next/dist/next-server/lib/router/utils')
|
||||
));
|
||||
const resolved = require_.resolve(
|
||||
'next/dist/next-server/lib/router/utils',
|
||||
{ paths: [entryPath] }
|
||||
);
|
||||
({ getRouteRegex, getSortedRoutes } = require_(resolved));
|
||||
if (typeof getRouteRegex !== 'function') {
|
||||
getRouteRegex = undefined;
|
||||
}
|
||||
@@ -1419,10 +1424,6 @@ export type LambdaGroup = {
|
||||
pseudoLayerUncompressedBytes: number;
|
||||
};
|
||||
|
||||
export const MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
|
||||
const LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * MIB;
|
||||
const LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * KIB;
|
||||
|
||||
export async function getPageLambdaGroups({
|
||||
entryPath,
|
||||
config,
|
||||
@@ -3025,3 +3026,35 @@ export function isApiPage(page: string | undefined) {
|
||||
.replace(/\\/g, '/')
|
||||
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
|
||||
}
|
||||
|
||||
export type VariantsManifest = Record<
|
||||
string,
|
||||
{
|
||||
defaultValue?: unknown;
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
>;
|
||||
|
||||
export async function getVariantsManifest(
|
||||
entryPath: string,
|
||||
outputDirectory: string
|
||||
): Promise<null | VariantsManifest> {
|
||||
const pathVariantsManifest = path.join(
|
||||
entryPath,
|
||||
outputDirectory,
|
||||
'variants-manifest.json'
|
||||
);
|
||||
|
||||
const hasVariantsManifest = await fs
|
||||
.access(pathVariantsManifest)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
|
||||
if (!hasVariantsManifest) return null;
|
||||
|
||||
const variantsManifest: VariantsManifest = await fs.readJSON(
|
||||
pathVariantsManifest
|
||||
);
|
||||
|
||||
return variantsManifest;
|
||||
}
|
||||
|
||||
1
packages/next/test/tsconfig.json
vendored
1
packages/next/test/tsconfig.json
vendored
@@ -2,6 +2,7 @@
|
||||
"extends": "../tsconfig.json",
|
||||
"include": ["**/*.test.ts"],
|
||||
"compilerOptions": {
|
||||
"types": ["jest"],
|
||||
"allowJs": true
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user