Skip to content

Commit ab9f2f5

Browse files
committed
feat: make aqora config directory configurable
based on : aqora-io/cli@20d8167
1 parent c1e5c8a commit ab9f2f5

File tree

6 files changed

+67
-65
lines changed

6 files changed

+67
-65
lines changed

src/commands/login/oauth2/callbackServer.ts

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,10 @@ import { GlobalArgs } from "../../../globalArgs";
66

77
const LOGIN_REPONSE_HTML_FILE = "login_response.html";
88

9-
const createServer = (
10-
port: number,
11-
onRequest: (
12-
req: http.IncomingMessage,
13-
res: http.ServerResponse,
14-
) => Promise<void>,
15-
) => {
16-
return new http.Server((req, res) => {
17-
onRequest(req, res).catch((err) => {
18-
res.writeHead(500);
19-
res.end("Internal Server Error");
20-
console.error(err);
21-
});
22-
}).listen(port, () =>
23-
console.info(
24-
`Listening for OAuth callback on http://127.0.0.1:${port}/callback`,
25-
));
26-
};
27-
28-
export const getAvailablePort = async (): Promise<number> => {
29-
const tempServer = http.createServer();
9+
export function getAvailablePort(): Promise<number> {
3010
return new Promise((resolve, reject) => {
11+
const tempServer = http.createServer();
12+
3113
tempServer.listen(0, () => {
3214
const address = tempServer.address();
3315
if (address && typeof address === "object") {
@@ -38,9 +20,11 @@ export const getAvailablePort = async (): Promise<number> => {
3820
}
3921
});
4022

41-
tempServer.on("error", (error: any) => reject(new Error(`Error finding available port: ${error.message}`)));
23+
tempServer.on("error", (error: any) => {
24+
reject(new Error(`Error finding available port: ${error.message}`));
25+
});
4226
});
43-
};
27+
}
4428

4529
const loadHtmlFile = async (filePath: string): Promise<string> => {
4630
try {
@@ -50,47 +34,50 @@ const loadHtmlFile = async (filePath: string): Promise<string> => {
5034
}
5135
};
5236

53-
const handleCallbackRequest = async (
54-
req: http.IncomingMessage,
55-
res: http.ServerResponse,
56-
): Promise<void> => {
57-
if (!req.url?.startsWith("/callback")) {
58-
res.writeHead(404);
59-
res.end("Not Found");
60-
return;
61-
}
62-
63-
const urlParams = new URLSearchParams(req.url.split("?")[1]);
64-
const authorizationCode = urlParams.get("code");
65-
66-
if (!authorizationCode) {
67-
res.writeHead(400);
68-
res.end("Invalid callback request");
69-
throw new Error("No authorization code found");
70-
}
37+
export function startLocalServerForCallback(port: number): Promise<string> {
38+
return new Promise((resolve, reject) => {
39+
const server = http.createServer(async (req, res) => {
40+
if (req.url?.startsWith("/callback")) {
41+
const urlParams = new URLSearchParams(req.url.split("?")[1]);
42+
const authorizationCode = urlParams.get("code");
7143

72-
const htmlFilePath = vscode.Uri.file(
73-
path.join(GlobalArgs.getExtensionPath(), "public", LOGIN_REPONSE_HTML_FILE),
74-
);
75-
const htmlContent = await loadHtmlFile(htmlFilePath.path);
44+
if (!authorizationCode) {
45+
res.writeHead(400);
46+
res.end("Invalid callback request");
47+
reject(new Error("No authorization code found"));
48+
return;
49+
}
50+
const htmlFilePath = vscode.Uri.file(
51+
path.join(
52+
GlobalArgs.getExtensionPath(),
53+
"public",
54+
LOGIN_REPONSE_HTML_FILE,
55+
),
56+
);
57+
const htmlContent = await loadHtmlFile(htmlFilePath.path);
7658

77-
res.writeHead(200, { "Content-Type": "text/html" });
78-
res.end(htmlContent);
79-
};
59+
res.writeHead(200, { "Content-Type": "text/html" });
60+
res.end(htmlContent);
61+
server.close();
8062

81-
export const startLocalServerForCallback = async (
82-
port: number,
83-
onClose?: () => void,
84-
): Promise<string | undefined> => {
85-
const server = createServer(port, handleCallbackRequest).close(onClose);
63+
resolve(authorizationCode);
64+
server.close();
65+
} else {
66+
res.writeHead(404);
67+
res.end("Not Found");
68+
}
69+
});
8670

87-
return new Promise((resolve, reject) => {
88-
server.on("close", () => {
89-
resolve(undefined);
71+
server.listen(port, () => {
72+
console.log(
73+
`Listening for OAuth callback on ${server.address()}:/callback`,
74+
);
9075
});
9176

92-
server.on("error", (err) => {
93-
reject(new Error(`Failed to start server: ${err.message}`));
77+
server.on("error", (error: any) => {
78+
reject(new Error(`Failed to start server: ${error.message}`));
9479
});
80+
81+
server.on("close", () => console.info("Server closed"));
9582
});
96-
};
83+
}

src/commands/login/oauth2/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import * as vscode from "vscode";
66
import { isUserConnected } from "../../../credentials";
77
import { base64UrlSafeEncode } from "../../utils";
88
import { clientId, createCredentials } from "../createCredentials";
9-
import { getAvailablePort, startLocalServerForCallback } from "./callbackServer";
9+
import {
10+
getAvailablePort,
11+
startLocalServerForCallback,
12+
} from "./callbackServer";
1013

1114
function authorizeUrl(clientId: string, redirectUri: URL, state: string): URL {
1215
const baseUrl = new URL("/oauth2/authorize", GlobalArgs.aqoraUrl());

src/credentials.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { DateTime } from "luxon";
55
import { credentialsPath, isAccessible } from "./dirs";
66
import { GlobalArgs } from "./globalArgs";
77
import { gql } from "./graphql";
8-
import { Refresh_TokenMutation, Refresh_TokenMutationVariables } from "./graphql/graphql";
8+
import {
9+
Refresh_TokenMutation,
10+
Refresh_TokenMutationVariables,
11+
} from "./graphql/graphql";
912
import { CamelToSnakeCaseNested } from "./utils";
1013

1114
const EXPIRATION_PADDING_SEC = 60;

src/dirs.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { promises as fs } from "fs";
22
import * as path from "path";
33
import xdgAppPaths from "xdg-app-paths";
4+
import { GlobalArgs } from "./globalArgs";
45

56
const CREDENTIALS_FILE = "credentials.json";
67
const PATH_SUFFIX = "aqora";
@@ -20,6 +21,7 @@ class SystemError extends Error {
2021
}
2122

2223
export async function configDir(): Promise<string> {
24+
console.log("READDDDDDD")
2325
const paths = xdgAppPaths({ name: PATH_SUFFIX });
2426

2527
if (await isAccessible(paths.data())) {
@@ -37,6 +39,7 @@ export async function configDir(): Promise<string> {
3739
}
3840
}
3941

42+
4043
export async function isAccessible(path: string): Promise<boolean> {
4144
try {
4245
await fs.access(path, fs.constants.R_OK);
@@ -47,7 +50,7 @@ export async function isAccessible(path: string): Promise<boolean> {
4750
}
4851

4952
export async function credentialsPath(): Promise<string> {
50-
return path.join(await configDir(), CREDENTIALS_FILE);
53+
return path.join(await GlobalArgs.getConfigHome(), CREDENTIALS_FILE);
5154
}
5255

5356
export function projectConfigDir(projectDir: string): string {

src/environment.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ declare global {
22
namespace NodeJS {
33
interface ProcessEnv {
44
NODE_ENV: "development" | "production";
5-
GRAPHQL_ENDPOINT?: "string";
5+
GRAPHQL_ENDPOINT?: string;
6+
AQORA_CONFIG_HOME?: string;
67
}
78
}
89
}

src/globalArgs.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { access, readFile, stat } from "fs/promises";
22
import { join } from "path";
33
import { URL } from "url";
44
import { window, workspace } from "vscode";
5+
import { configDir } from "./dirs";
56

67
export type AqoraProjectType = "submission" | "use_case";
78

@@ -29,12 +30,14 @@ export interface GlobalArgsProps {
2930
isAqoraProject: (customPath?: string) => Promise<boolean>;
3031
aqoraProject: (customPath?: string) => Promise<AqoraProject | undefined>;
3132
currentPath: () => string | undefined;
33+
getConfigHome: () => Promise<string>;
3234
getExtensionPath: () => string;
3335
setExtensionPath: (path: string) => void;
3436
}
3537

3638
export const GlobalArgs: GlobalArgsProps = (() => {
3739
const config = workspace.getConfiguration();
40+
console.log("AQORA CONFIG", config.get("aqora"));
3841
const url = new URL(config.get<string>("aqora.url") || "https://aqora.io");
3942
const noPrompt = config.get<boolean>("aqora.noPrompt") ?? true;
4043

@@ -82,8 +85,8 @@ export const GlobalArgs: GlobalArgsProps = (() => {
8285
const isAqoraProject = async (customPath?: string): Promise<boolean> => {
8386
const project = await getAqoraProject(customPath);
8487
return (
85-
project?.tool.aqora.type === "use_case"
86-
|| project?.tool.aqora.type === "submission"
88+
project?.tool.aqora.type === "use_case" ||
89+
project?.tool.aqora.type === "submission"
8790
);
8891
};
8992

@@ -94,6 +97,8 @@ export const GlobalArgs: GlobalArgsProps = (() => {
9497
get noPrompt() {
9598
return noPrompt;
9699
},
100+
getConfigHome: async () =>
101+
config.get<string>("aqora.configHome") || (await configDir()),
97102
aqoraUrl: () => new URL(url),
98103
graphqlUrl: () => new URL("/graphql", url),
99104
isAqoraProject,

0 commit comments

Comments
 (0)