Skip to content

Vercel integration #348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 115 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
a69129d
Vercel integration
N2D4 Nov 24, 2024
06ac353
Merge branch 'dev' into vercel-integration
N2D4 Dec 10, 2024
2ed6081
Merge branch 'dev' into vercel-integration
N2D4 Dec 10, 2024
2b9ce9a
Merge branch 'dev' into vercel-integration
N2D4 Dec 27, 2024
4891271
Merge branch 'dev' into vercel-integration
N2D4 Feb 6, 2025
67e1e7a
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
f6cf55f
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
4e2d4a6
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
7e987a7
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
69d590f
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
4df91f0
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
43089f5
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
2c71976
Merge dev into vercel-integration
github-actions[bot] Mar 5, 2025
54bd5be
Merge dev into vercel-integration
github-actions[bot] Mar 6, 2025
adb8711
Merge dev into vercel-integration
github-actions[bot] Mar 6, 2025
c5b5b70
Merge dev into vercel-integration
github-actions[bot] Mar 7, 2025
12cc170
Merge dev into vercel-integration
github-actions[bot] Mar 7, 2025
1954ed7
Merge dev into vercel-integration
github-actions[bot] Mar 7, 2025
36bf319
Merge dev into vercel-integration
N2D4 Mar 7, 2025
bbdb3c9
Merge dev into vercel-integration
N2D4 Mar 8, 2025
3e3854f
Merge dev into vercel-integration
N2D4 Mar 9, 2025
cad9721
Merge dev into vercel-integration
N2D4 Mar 9, 2025
60935c2
Merge dev into vercel-integration
N2D4 Mar 10, 2025
dae31dd
Merge dev into vercel-integration
N2D4 Mar 10, 2025
8192f44
Merge dev into vercel-integration
N2D4 Mar 10, 2025
cf704ed
Merge dev into vercel-integration
N2D4 Mar 10, 2025
2dbe8d9
Merge dev into vercel-integration
N2D4 Mar 10, 2025
fafe71c
Merge dev into vercel-integration
N2D4 Mar 10, 2025
9b6db42
Merge dev into vercel-integration
N2D4 Mar 10, 2025
7a27fa8
Merge dev into vercel-integration
N2D4 Mar 10, 2025
bb9200b
Merge dev into vercel-integration
N2D4 Mar 10, 2025
3758c03
Merge dev into vercel-integration
N2D4 Mar 10, 2025
3514978
Merge dev into vercel-integration
N2D4 Mar 10, 2025
16f416f
Merge dev into vercel-integration
N2D4 Mar 10, 2025
98ff26a
Merge dev into vercel-integration
N2D4 Mar 10, 2025
fbae0a4
Merge dev into vercel-integration
N2D4 Mar 12, 2025
0354e39
Merge dev into vercel-integration
N2D4 Mar 12, 2025
14dc69f
Merge dev into vercel-integration
N2D4 Mar 12, 2025
984245e
Merge dev into vercel-integration
N2D4 Mar 12, 2025
7f85e1f
Merge dev into vercel-integration
N2D4 Mar 12, 2025
9729500
Merge dev into vercel-integration
N2D4 Mar 12, 2025
ef86146
Merge dev into vercel-integration
N2D4 Mar 12, 2025
7beeccd
Merge dev into vercel-integration
N2D4 Mar 12, 2025
2be20d9
Merge dev into vercel-integration
N2D4 Mar 12, 2025
e995115
Merge dev into vercel-integration
N2D4 Mar 12, 2025
7e67ad3
Merge dev into vercel-integration
N2D4 Mar 13, 2025
521f1fd
Merge dev into vercel-integration
N2D4 Mar 13, 2025
bb2b2f6
Merge dev into vercel-integration
N2D4 Mar 13, 2025
03a59ca
Merge dev into vercel-integration
N2D4 Mar 14, 2025
9e55950
Merge dev into vercel-integration
N2D4 Mar 15, 2025
ac7ac94
Merge dev into vercel-integration
N2D4 Mar 17, 2025
fad703c
Merge dev into vercel-integration
N2D4 Mar 19, 2025
f3bc21c
Merge dev into vercel-integration
N2D4 Mar 20, 2025
2c8d4b5
Merge dev into vercel-integration
N2D4 Mar 20, 2025
4cb5774
Merge dev into vercel-integration
N2D4 Mar 20, 2025
134b92c
Merge dev into vercel-integration
N2D4 Mar 21, 2025
ea22715
Merge dev into vercel-integration
N2D4 Mar 22, 2025
1bc72fd
Merge dev into vercel-integration
N2D4 Mar 23, 2025
435ab9a
Merge dev into vercel-integration
N2D4 Mar 24, 2025
218f3ae
Merge dev into vercel-integration
N2D4 Mar 25, 2025
6f94c6e
Merge dev into vercel-integration
N2D4 Mar 26, 2025
ddecd00
Merge dev into vercel-integration
N2D4 Mar 27, 2025
043d470
Merge dev into vercel-integration
N2D4 Mar 28, 2025
ac931da
Merge dev into vercel-integration
N2D4 Apr 1, 2025
26ca44e
Merge dev into vercel-integration
N2D4 Apr 2, 2025
3143525
Merge dev into vercel-integration
N2D4 Apr 3, 2025
03e5247
Merge dev into vercel-integration
N2D4 Apr 4, 2025
7900be2
Merge dev into vercel-integration
N2D4 Apr 5, 2025
3079fcb
Merge dev into vercel-integration
N2D4 Apr 8, 2025
226c57f
Merge dev into vercel-integration
N2D4 Apr 9, 2025
abc9b8a
Merge dev into vercel-integration
N2D4 Apr 10, 2025
d29e528
Merge dev into vercel-integration
N2D4 Apr 11, 2025
bf68f25
Merge dev into vercel-integration
N2D4 Apr 12, 2025
5319990
Merge dev into vercel-integration
N2D4 Apr 13, 2025
40c35ea
Merge dev into vercel-integration
N2D4 Apr 15, 2025
1a15753
Merge dev into vercel-integration
N2D4 Apr 16, 2025
9f591f0
Merge dev into vercel-integration
N2D4 Apr 18, 2025
325c098
Merge dev into vercel-integration
N2D4 Apr 23, 2025
5d57a03
Merge dev into vercel-integration
N2D4 Apr 24, 2025
f85026b
Merge dev into vercel-integration
N2D4 Apr 26, 2025
782463d
Merge dev into vercel-integration
N2D4 Apr 28, 2025
4bdeed5
Merge dev into vercel-integration
N2D4 Apr 29, 2025
800ee13
Merge dev into vercel-integration
N2D4 Apr 30, 2025
3c1fdda
Merge dev into vercel-integration
N2D4 May 1, 2025
3dd9ab1
Merge dev into vercel-integration
N2D4 May 5, 2025
0487a09
Merge dev into vercel-integration
N2D4 May 7, 2025
d9a00ee
Merge dev into vercel-integration
N2D4 May 8, 2025
773252a
Merge dev into vercel-integration
N2D4 May 13, 2025
37df6ee
Merge dev into vercel-integration
N2D4 May 14, 2025
e922d45
Merge dev into vercel-integration
N2D4 May 15, 2025
24162ae
Merge dev into vercel-integration
N2D4 May 16, 2025
2f9c68b
Merge dev into vercel-integration
N2D4 May 17, 2025
2a50db5
Merge dev into vercel-integration
N2D4 May 20, 2025
beca1cc
Merge dev into vercel-integration
N2D4 May 22, 2025
42eb2c9
Merge dev into vercel-integration
N2D4 May 23, 2025
5fada42
Merge dev into vercel-integration
N2D4 May 24, 2025
b7e2ed5
Merge dev into vercel-integration
N2D4 May 27, 2025
2ee8220
Merge dev into vercel-integration
N2D4 Jun 3, 2025
45f2ff8
Merge dev into vercel-integration
N2D4 Jun 6, 2025
36f1c6d
Merge dev into vercel-integration
N2D4 Jun 7, 2025
9c9d54b
Merge dev into vercel-integration
N2D4 Jun 12, 2025
916862b
Merge dev into vercel-integration
N2D4 Jun 18, 2025
9892919
Merge dev into vercel-integration
N2D4 Jun 19, 2025
93f24df
Merge dev into vercel-integration
N2D4 Jun 20, 2025
e0e74a5
Merge dev into vercel-integration
N2D4 Jun 21, 2025
5599106
Merge dev into vercel-integration
N2D4 Jun 23, 2025
21c8a17
Merge dev into vercel-integration
N2D4 Jun 24, 2025
5b9e4ee
Merge dev into vercel-integration
N2D4 Jun 27, 2025
201ab09
Merge dev into vercel-integration
N2D4 Jun 28, 2025
059e911
Merge dev into vercel-integration
N2D4 Jul 1, 2025
04dfcef
Merge dev into vercel-integration
N2D4 Jul 2, 2025
d2c45d0
Merge dev into vercel-integration
N2D4 Jul 3, 2025
1cf9dbc
Merge dev into vercel-integration
N2D4 Jul 4, 2025
ed02f12
Merge dev into vercel-integration
N2D4 Jul 5, 2025
97846cf
Merge dev into vercel-integration
N2D4 Jul 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/stack-shared/src/utils/urls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import.meta.vitest?.test("createUrlIfValid", ({ expect }) => {
});

export function isValidUrl(url: string) {
return !!createUrlIfValid(url);
return createUrlIfValid(url) !== null;
}
import.meta.vitest?.test("isValidUrl", ({ expect }) => {
// Test with valid URLs
Expand Down
115 changes: 115 additions & 0 deletions packages/stack-shared/src/utils/vercel-api.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { StackAssertionError } from "./errors";
import { Json, parseJson } from "./json";
import { Result } from "./results";
import { createUrlIfValid, isValidUrl } from "./urls";

async function vercelApiRequest(options: { token: string, path: string, method: string, query?: Record<string, string>, body?: Json }): Promise<Result<any>> {
const url = new URL(options.path, `https://api.vercel.com`);
if (options.query) {
for (const [key, value] of Object.entries(options.query)) {
url.searchParams.set(key, value);
}
}
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${options.token}`,
'Content-Type': 'application/json',
},
method: options.method,
body: options.body ? JSON.stringify(options.body) : undefined,
});
if (!res.ok) {
const text = await res.text();
let errorMessage = text;
let errorCode: string | undefined;

const maybeJson = parseJson(text);
if (maybeJson.status === "ok") {
const json: any = maybeJson.data;
errorMessage = json?.error?.message ?? errorMessage;
errorCode = json?.error?.code ?? errorCode;
}

return Result.error(new StackAssertionError(`Vercel API returned ${res.status} ${res.statusText}: ${errorMessage}`, {
status: res.status,
code: errorCode,
text,
response: res,
}));
}
const data = await res.json();
return Result.ok(data);
}

export async function getCurrentUser(options: { token: string }): Promise<Result<{ id: string, email: string, name: string }>> {
return await vercelApiRequest({
token: options.token,
path: '/v2/user',
method: 'GET',
});
}

export function parseProjectUrl(projectUrl: string): Result<{ teamSlug: string, projectName: string }> {
let projectUrlWithProto = projectUrl.includes("://") ? projectUrl : `https://${projectUrl}`;
const url = createUrlIfValid(projectUrlWithProto);
if (url === null) {
return Result.error(new StackAssertionError(`Invalid project URL`));
}
if (url.hostname !== "vercel.com") {
return Result.error(new StackAssertionError(`Project URL must have the hostname "vercel.com"`));
}
const path = url.pathname.startsWith("/") ? url.pathname.slice(1) : url.pathname;
const parts = path.split("/");
if (parts.length !== 2) {
return Result.error(new StackAssertionError(`Project URL must be of the form "vercel.com/<team-slug>/<project-slug>"`));
}
const teamSlug = parts[0];
const projectName = parts[1];
return Result.ok({ teamSlug, projectName });
}


export async function getProject(options: { token: string, teamSlug: string, idOrName: string }): Promise<Result<{
id: string,
name: string,
}>> {
return await vercelApiRequest({
token: options.token,
path: `/v9/projects/${options.idOrName}`,
query: {
slug: options.teamSlug,
},
method: 'GET',
});
}

export async function getDeployment(options: { token: string, teamSlug: string } & ({ id: string } | { url: string })): Promise<Result<{
id: string,
url: string,
public: boolean,
team: {
id: string,
slug: string,
},
}>> {
let idOrUrl: string;
if ("id" in options) {
if (isValidUrl(options.id)) {
return Result.error(new StackAssertionError(`Invalid deployment ID, should not be a URL: ${options.id}`));
}
idOrUrl = options.id;
} else {
if (!isValidUrl(options.url)) {
return Result.error(new StackAssertionError(`Invalid deployment URL: ${options.url}`));
}
idOrUrl = options.url;
}
return await vercelApiRequest({
token: options.token,
path: `/v13/deployments/${idOrUrl}`,
query: {
slug: options.teamSlug,
},
method: 'GET',
});
}