Skip to content

Commit

Permalink
feat: add support for teams! (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarondill authored Feb 13, 2024
1 parent b68c622 commit 983c549
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 98 deletions.
2 changes: 1 addition & 1 deletion src/commands/Environment/createEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class CreateEnvironment implements Command {
public readonly id = "vercel.createEnvironment";
constructor(private readonly vercel: VercelManager) {}
async execute() {
if (!((await this.vercel.auth) && this.vercel.selectedProject)) return;
if (!this.vercel.selectedProject) return;

const envlist = (await this.vercel.env.getEnvList())?.map(x => x.key);
if (!envlist) throw new Error("Failed to get environment list");
Expand Down
2 changes: 1 addition & 1 deletion src/commands/Environment/removeEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class RemoveEnvironment implements Command {
public readonly id = "vercel.removeEnvironment";
constructor(private readonly vercel: VercelManager) {}
async execute(command?: { envId: string; key: string }) {
if (!((await this.vercel.auth) && this.vercel.selectedProject)) return;
if (!this.vercel.selectedProject) return;
//> Get information from arguments if given
let id: string | undefined = command?.envId;
let key: string | undefined = command?.key;
Expand Down
3 changes: 2 additions & 1 deletion src/commands/Environment/setEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export class SetEnvironment implements Command {
key: string;
editing: "TARGETS" | "VALUE";
}) {
if (!((await this.vercel.auth) && this.vercel.selectedProject)) return;
if (!this.vercel.selectedProject) return;
if (!(await this.vercel.loggedIn())) return;

//> Get info from arguments if given
let id: string | undefined = command?.id;
Expand Down
3 changes: 2 additions & 1 deletion src/features/EnvironmentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export class EnvironmentProvider
];
return items;
}
if (!this.vercel.selectedProject || !(await this.vercel.auth)) return [];
if (!this.vercel.selectedProject || !(await this.vercel.loggedIn()))
return [];
const items: vscode.TreeItem[] = [new CreateEnvironment()];
const res = await this.vercel.env.getAll();
if (res.length > 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/features/StatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class StatusBar {
}

public async updateStatus(): Promise<void> {
if (!(await this.vercel.auth)) {
if (!(await this.vercel.loggedIn())) {
this.text = "Login";
this.tooltip = "Click to login";
return;
Expand Down
19 changes: 14 additions & 5 deletions src/features/TokenManager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as vscode from "vscode";
import path from "path";
import { parseJsonObject } from "../utils/jsonParse";
import type { OauthResult } from "../utils/oauth";

export class TokenManager {
private readonly authKey = "vercel_token";
private readonly teamIdKey = "vercel_team_id";
private readonly projectKey = "vercel_selected_project";

private readonly onAuthStateChanged: (state: boolean) => void;
Expand Down Expand Up @@ -80,14 +82,21 @@ export class TokenManager {
});
}

setAuth(token: string | undefined) {
async setAuth(token: OauthResult | undefined) {
this.onAuthStateChanged(!!token);
if (token === undefined) return this.secrets.delete(this.authKey);
return this.secrets.store(this.authKey, token);
if (token?.accessToken)
await this.secrets.store(this.authKey, token.accessToken);
else await this.secrets.delete(this.authKey);

if (token?.teamId) await this.secrets.store(this.teamIdKey, token.teamId);
else await this.secrets.delete(this.authKey);
}

getAuth(): Thenable<string | undefined> {
return this.secrets.get(this.authKey);
async getAuth(): Promise<OauthResult | undefined> {
const accessToken = await this.secrets.get(this.authKey);
if (!accessToken) return undefined; // We will never have a (valid) teamid without a token!
const teamId = (await this.secrets.get(this.teamIdKey)) ?? null;
return { accessToken, teamId };
}

async setProject(token: string | undefined) {
Expand Down
69 changes: 25 additions & 44 deletions src/features/VercelManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ export class VercelManager {

private projectInfo: VercelResponse.info.project | null = null;
private userInfo: VercelResponse.info.User | null = null;
private api: Api;

public constructor(private readonly token: TokenManager) {
const refreshRate = workspace
.getConfiguration("vercel")
.get("RefreshRate") as number;
this.api = new Api(token);
const refreshRate = Number(
workspace.getConfiguration("vercel").get("RefreshRate")
);
setInterval(
() => {
this.onDidDeploymentsUpdated();
Expand All @@ -42,9 +44,12 @@ export class VercelManager {
this.userInfo = null;
};
}
async loggedIn() {
return !!(await this.token.getAuth())?.accessToken;
}

async logIn(): Promise<boolean> {
const apiToken = await getTokenOauth();
const apiToken = await getTokenOauth(this.api);
if (!apiToken) return false;
await this.token.setAuth(apiToken);
this.onDidDeploymentsUpdated();
Expand All @@ -69,28 +74,16 @@ export class VercelManager {
get selectedProject() {
return this.token.getProject();
}
/** Utility getter to return authentication token */
get auth() {
return this.token.getAuth();
}
/** Utility getter to return the proper fetch options for authentication */
private async authHeader() {
const auth = await this.auth;
if (!auth) throw new Error("Not authenticated. Ensure user is logged in!");
return {
headers: { Authorization: `Bearer ${auth}` },
};
}

project = {
getInfo: async (refresh: boolean = false) => {
if (this.projectInfo !== null && !refresh) return this.projectInfo;
const selectedProject = this.selectedProject;
if (!selectedProject)
return void window.showErrorMessage("No project selected!");
const result = await Api.projectInfo(
const result = await this.api.projectInfo(
{ projectId: selectedProject },
await this.authHeader()
{}
);
if (!result.ok) return;
return (this.projectInfo = result);
Expand All @@ -99,7 +92,7 @@ export class VercelManager {
user = {
getInfo: async (refresh: boolean = false) => {
if (this.userInfo !== null && !refresh) return this.userInfo;
const response = await Api.userInfo({}, await this.authHeader());
const response = await this.api.userInfo(undefined, undefined);
if (!response.ok) return;
return (this.userInfo = response.user);
},
Expand All @@ -111,10 +104,10 @@ export class VercelManager {
* or undefined if no project is selected or no user is authenticated
*/
getAll: async (): Promise<VercelEnvironmentInformation[]> => {
if (!(await this.auth) || !this.selectedProject) return [];
const response = await Api.environment.getAll(
if (!this.selectedProject) return [];
const response = await this.api.environment.getAll(
{ projectId: this.selectedProject },
await this.authHeader()
undefined
);
if (!response.ok) return (this.envList = []);
const r = "envs" in response ? response.envs ?? [] : [response];
Expand All @@ -134,9 +127,9 @@ export class VercelManager {
const projectId = this.selectedProject;
if (!projectId)
return void window.showErrorMessage("No project selected!");
await Api.environment.create(
await this.api.environment.create(
{ projectId, body: { key, value, target, type: "encrypted" } },
await this.authHeader()
undefined
);
this.onDidEnvironmentsUpdated();
},
Expand All @@ -149,7 +142,7 @@ export class VercelManager {
const projectId = this.selectedProject;
if (!projectId)
return void window.showErrorMessage("No project selected!");
await Api.environment.remove({ projectId, id }, await this.authHeader());
await this.api.environment.remove({ projectId, id }, undefined);
this.onDidEnvironmentsUpdated();
},
/**
Expand All @@ -162,18 +155,9 @@ export class VercelManager {
const selectedProject = this.selectedProject;
if (!selectedProject)
return void window.showErrorMessage("No project selected!");
await Api.environment.edit(
{
projectId: selectedProject,
id,
body: {
value,
target: targets,
},
},
{
headers: (await this.authHeader()).headers,
}
await this.api.environment.edit(
{ projectId: selectedProject, id, body: { value, target: targets } },
undefined
);
this.onDidEnvironmentsUpdated();
},
Expand All @@ -191,18 +175,15 @@ export class VercelManager {
* user or empty list if either doesn't exist
*/
getAll: async () => {
if (!this.selectedProject || !(await this.auth)) return [];
if (!this.selectedProject) return [];
try {
this.fetchingDeployments = true;
const limit = workspace
.getConfiguration("vercel")
.get("DeploymentCount") as number;
const data = await Api.deployments(
{
projectId: this.selectedProject,
limit: limit ?? 20,
},
await this.authHeader()
const data = await this.api.deployments(
{ projectId: this.selectedProject, limit: limit ?? 20 },
undefined
);
if (!data.ok) return (this.deploymentsList = []);
const r = data.deployments ?? [];
Expand Down
Loading

0 comments on commit 983c549

Please sign in to comment.