Skip to content

Commit b806d23

Browse files
ericallamTrigger.dev RepoOps
authored andcommitted
perf(webapp): load only the Vercel API endpoints the integration calls
The Vercel integration's API client is now built from the Vercel SDK's standalone functions, so each webapp process loads only the endpoints the integration calls instead of the whole SDK. This lowers the webapp's baseline memory use and startup time. Mono-RevId: 274094829755687c75100d85e5b481b356725cc8
1 parent f6238d0 commit b806d23

2 files changed

Lines changed: 74 additions & 2 deletions

File tree

‎apps/webapp/app/models/vercelIntegration.server.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
mergeVercelEnvironmentVariableValues,
88
} from "~/v3/vercel/environmentVariableValues";
99
import pLimit from "p-limit";
10-
import { Vercel } from "@vercel/sdk";
1110
import type {
1211
ResponseBodyEnvs,
1312
FilterProjectEnvsResponseBody,
@@ -36,6 +35,7 @@ import { EnvironmentVariablesRepository } from "~/v3/environmentVariables/enviro
3635
import { isReservedForExternalSync } from "~/v3/environmentVariableRules.server";
3736
import { boundedIn } from "@trigger.dev/database";
3837
import { toVercelApiError, type VercelApiError } from "~/v3/vercel/vercelApiError";
38+
import { createVercelClient, type VercelClient as Vercel } from "~/v3/vercel/vercelClient.server";
3939
import {
4040
callVercelWithRecovery,
4141
wrapVercelCallWithRecovery,
@@ -305,7 +305,7 @@ export class VercelIntegrationRepository {
305305
throw new Error("Failed to get Vercel access token");
306306
}
307307
return {
308-
client: new Vercel({ bearerToken: secret.accessToken }),
308+
client: createVercelClient({ bearerToken: secret.accessToken }),
309309
accessToken: secret.accessToken,
310310
};
311311
})(),
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { VercelCore } from "@vercel/sdk/core";
2+
import { environmentGetSharedEnvVar } from "@vercel/sdk/funcs/environmentGetSharedEnvVar";
3+
import { environmentGetV9ProjectsIdOrNameCustomEnvironments } from "@vercel/sdk/funcs/environmentGetV9ProjectsIdOrNameCustomEnvironments";
4+
import { integrationsDeleteConfiguration } from "@vercel/sdk/funcs/integrationsDeleteConfiguration";
5+
import { projectsBatchRemoveProjectEnv } from "@vercel/sdk/funcs/projectsBatchRemoveProjectEnv";
6+
import { projectsCreateProjectEnv } from "@vercel/sdk/funcs/projectsCreateProjectEnv";
7+
import { projectsEditProjectEnv } from "@vercel/sdk/funcs/projectsEditProjectEnv";
8+
import { projectsFilterProjectEnvs } from "@vercel/sdk/funcs/projectsFilterProjectEnvs";
9+
import { projectsGetProjectEnv } from "@vercel/sdk/funcs/projectsGetProjectEnv";
10+
import { projectsGetProjects } from "@vercel/sdk/funcs/projectsGetProjects";
11+
import { projectsUpdateProject } from "@vercel/sdk/funcs/projectsUpdateProject";
12+
import { teamsGetTeam } from "@vercel/sdk/funcs/teamsGetTeam";
13+
import { userGetAuthUser } from "@vercel/sdk/funcs/userGetAuthUser";
14+
import type { RequestOptions } from "@vercel/sdk/lib/sdks";
15+
import type { Result } from "@vercel/sdk/types/fp";
16+
17+
/**
18+
* A Vercel API client with the same call shape as `new Vercel()` from `@vercel/sdk`,
19+
* built from the SDK's standalone functions so only the endpoints we call are loaded.
20+
* The `Vercel` class pulls in every endpoint's schemas, about 250 MB of heap per process.
21+
* Add a method here when the integration needs a new endpoint.
22+
*/
23+
export function createVercelClient(options: { bearerToken: string }) {
24+
const core = new VercelCore(options);
25+
26+
const bind =
27+
<Request, Response>(
28+
func: (
29+
client: VercelCore,
30+
request: Request,
31+
options?: RequestOptions
32+
) => Promise<Result<Response, unknown>>
33+
) =>
34+
async (request: Request, options?: RequestOptions): Promise<Response> =>
35+
unwrap(await func(core, request, options));
36+
37+
return {
38+
environment: {
39+
getSharedEnvVar: bind(environmentGetSharedEnvVar),
40+
getV9ProjectsIdOrNameCustomEnvironments: bind(
41+
environmentGetV9ProjectsIdOrNameCustomEnvironments
42+
),
43+
},
44+
integrations: {
45+
deleteConfiguration: bind(integrationsDeleteConfiguration),
46+
},
47+
projects: {
48+
batchRemoveProjectEnv: bind(projectsBatchRemoveProjectEnv),
49+
createProjectEnv: bind(projectsCreateProjectEnv),
50+
editProjectEnv: bind(projectsEditProjectEnv),
51+
filterProjectEnvs: bind(projectsFilterProjectEnvs),
52+
getProjectEnv: bind(projectsGetProjectEnv),
53+
getProjects: bind(projectsGetProjects),
54+
updateProject: bind(projectsUpdateProject),
55+
},
56+
teams: {
57+
getTeam: bind(teamsGetTeam),
58+
},
59+
user: {
60+
getAuthUser: async (options?: RequestOptions) => unwrap(await userGetAuthUser(core, options)),
61+
},
62+
};
63+
}
64+
65+
export type VercelClient = ReturnType<typeof createVercelClient>;
66+
67+
function unwrap<Value>(result: Result<Value, unknown>): Value {
68+
if (!result.ok) {
69+
throw result.error;
70+
}
71+
return result.value;
72+
}

0 commit comments

Comments
 (0)