diff --git a/cli/package.json b/cli/package.json index 9220a92..4f98737 100644 --- a/cli/package.json +++ b/cli/package.json @@ -22,6 +22,7 @@ "@types/inquirer": "^9.0.7", "axios": "^1.7.2", "bun": "^1.1.8", + "dotenv": "^16.4.5", "execa": "^9.1.0", "inquirer": "^9.2.21", "install": "^0.13.0", diff --git a/cli/src/endpoints/authAxios.ts b/cli/src/endpoints/authAxios.ts index 74769c3..9316f51 100644 --- a/cli/src/endpoints/authAxios.ts +++ b/cli/src/endpoints/authAxios.ts @@ -1,11 +1,12 @@ import axios from "axios"; +import { GetCredentials } from "../utils/getCredentials"; export const axiosInstance = axios.create({ withCredentials: true, // Ensure credentials are sent with every request }); export const config = { - baseUrl: "https://routes-orcin.vercel.app", + baseUrl: process.env.DEVDB_URL ?? "https://routes-orcin.vercel.app", }; export function SetCookie(credentials: string) { @@ -23,3 +24,8 @@ export function SetCookie(credentials: string) { }, ); } + +if (process.env.DEVDB_TOKEN && process.env.DEVDB_URL) { + config.baseUrl = process.env.DEVDB_URL; + SetCookie(GetCredentials(process.env.DEVDB_TOKEN)); +} diff --git a/cli/src/endpoints/getProjects.ts b/cli/src/endpoints/getProjects.ts deleted file mode 100644 index 609b773..0000000 --- a/cli/src/endpoints/getProjects.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Project } from "../types"; -import { axiosInstance, config } from "./authAxios"; - -export default async function GetProjects() { - const fullUrl = `${config.baseUrl}/api/trpc/database.get?input=${encodeURIComponent(JSON.stringify({ json: { searchTerms: "" } }))}`; - - const response = await axiosInstance.get(fullUrl); - - const { result } = response.data as { result: { data: { json: Project[] } } }; - - const projects = result.data.json; - - return projects; -} diff --git a/cli/src/endpoints/projectEndpoints.ts b/cli/src/endpoints/projectEndpoints.ts new file mode 100644 index 0000000..266fa24 --- /dev/null +++ b/cli/src/endpoints/projectEndpoints.ts @@ -0,0 +1,90 @@ +import type { Project } from "../types"; +import { axiosInstance, config } from "./authAxios"; + +export async function GetProjects(): Promise { + const fullUrl = `${config.baseUrl}/api/trpc/database.get?input=${encodeURIComponent(JSON.stringify({ json: { searchTerms: "" } }))}`; + + const response = await axiosInstance.get(fullUrl); + + const { result } = response.data as { result: { data: { json: Project[] } } }; + + const projects = result.data.json; + + return projects; +} + +export async function CreateProject(repoUrl: string): Promise { + const { status } = await axiosInstance.post( + `${config.baseUrl}/api/trpc/database.create`, + { + json: { + repoUrl: repoUrl, + provider: "postgres", + }, + }, + ); + + return status === 200; +} + +export async function DeleteProject(repoUrl: string): Promise { + const { status } = await axiosInstance.post( + `${config.baseUrl}/api/trpc/database.delete`, + { + json: { + repoUrl: repoUrl, + }, + }, + ); + + return status === 200; +} + +export async function StartProject(repoUrl: string): Promise { + const { status } = await axiosInstance.post( + `${config.baseUrl}/api/trpc/database.start`, + { + json: { + repoUrl: repoUrl, + }, + }, + ); + + return status === 200; +} + +export async function StopProject(repoUrl: string): Promise { + const { status } = await axiosInstance.post( + `${config.baseUrl}/api/trpc/database.stop`, + { + json: { + repoUrl: repoUrl, + }, + }, + ); + + return status === 200; +} + +export async function GetEndpoint( + repoUrl: string, +): Promise { + const response = await axiosInstance.post( + `${config.baseUrl}/api/trpc/database.endpoint`, + { + json: { + repoUrl: repoUrl, + }, + }, + ); + + const { status } = response; + + const { result } = response.data as { result: { data: { json: string } } }; + + if (status === 200) { + return result.data.json; + } + + return; +} diff --git a/cli/src/index.ts b/cli/src/index.ts index 3e5403f..1221941 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -3,6 +3,7 @@ import SetupCLI from "./menu/setup"; import ViewProjects from "./menu/projects"; import inquirer from "inquirer"; +import "dotenv/config"; type MainAnswers = { selectedMenu: "setup" | "projects" | "exit"; @@ -35,17 +36,22 @@ async function GetMainAnswers(): Promise { * c. Project 3 */ async function main() { - const { selectedMenu } = await GetMainAnswers(); + console.log(process.env); - switch (selectedMenu) { - case "setup": - await SetupCLI(); - break; - case "projects": - await ViewProjects(); - break; - default: - process.exit(1); + if (!(process.env.DEVDB_TOKEN && process.env.DEVDB_URL)) { + await SetupCLI(); + } else { + const { selectedMenu } = await GetMainAnswers(); + switch (selectedMenu) { + case "setup": + await SetupCLI(); + break; + case "projects": + await ViewProjects(); + break; + default: + process.exit(0); + } } await main(); diff --git a/cli/src/menu/projects.ts b/cli/src/menu/projects.ts index bfb3afc..8242d08 100644 --- a/cli/src/menu/projects.ts +++ b/cli/src/menu/projects.ts @@ -1,6 +1,14 @@ import inquirer from "inquirer"; -import GetProjects from "../endpoints/getProjects"; +import { + CreateProject, + DeleteProject, + GetEndpoint, + GetProjects, + StartProject, + StopProject, +} from "../endpoints/projectEndpoints"; import type { Project } from "../types"; +import updateExistingEnvVariable from "../utils/updateEnv"; type ProjectAnswers = { selectedProject: string; @@ -20,7 +28,7 @@ async function SelectProject(projectNames: string[]): Promise { } type ProjectOptionsAnswers = { - selectedOption: string; + selectedOption: "start" | "stop" | "create" | "delete" | "endpoint" | "back"; }; async function SelectProjectOption( @@ -29,8 +37,8 @@ async function SelectProjectOption( return (await inquirer.prompt([ { type: "list", - name: "selectedProject", - message: "Select a project", + name: "selectedOption", + message: "Select an option", choices: validOptions, }, ])) as ProjectOptionsAnswers; @@ -56,27 +64,50 @@ export default async function ViewProjects() { } } +function LogSuccess(success: boolean, pastTense: string, presentTense: string) { + console.log( + success + ? `✅ Successfully ${pastTense} project` + : `❌ Failed ${presentTense} project`, + ); +} + async function ViewProjectOptions(project: Project) { console.log(project); - const { status } = project; + const { status, repository } = project; const validOptions = status === "available" - ? ["stop", "delete", "back"] - : ["start", "delete", "back"]; + ? ["stop", "endpoint", "delete", "back"] + : ["start", "endpoint", "delete", "back"]; const { selectedOption } = await SelectProjectOption(validOptions); + console.log(`selected option: ${selectedOption}`); + switch (selectedOption) { case "start": + const startSuccess = await StartProject(repository); + LogSuccess(startSuccess, "started", "starting"); break; case "stop": + const stopSuccess = await StopProject(repository); + LogSuccess(stopSuccess, "stopped", "stopping"); break; case "create": + const createSuccess = await CreateProject(repository); + LogSuccess(createSuccess, "created", "creating"); break; case "delete": + const deleteSuccess = await DeleteProject(repository); + LogSuccess(deleteSuccess, "deleted", "deleting"); break; case "endpoint": + const endpoint = await GetEndpoint(repository); + if (endpoint) { + await updateExistingEnvVariable("DATABASE_URL", endpoint); + } + LogSuccess(endpoint !== undefined, "set", "setting"); break; case "back": // Do nothing diff --git a/cli/src/menu/setup.ts b/cli/src/menu/setup.ts index 22f650e..2728255 100644 --- a/cli/src/menu/setup.ts +++ b/cli/src/menu/setup.ts @@ -45,6 +45,7 @@ export default async function SetupCLI() { process.exit(1); } else { await updateExistingEnvVariable("DEVDB_URL", backendUrl); + process.env.DEVDB_URL = backendUrl; config.baseUrl = backendUrl; console.log("✅ Successfully reached the backend"); } @@ -56,7 +57,7 @@ export default async function SetupCLI() { // Verify session token is valid try { console.log(`Attempting to authenticated token`); - const credentials = await GetCredentials(config.baseUrl, sessionToken); + const credentials = GetCredentials(sessionToken); SetCookie(credentials); const { status } = await axiosInstance.get( @@ -67,6 +68,7 @@ export default async function SetupCLI() { process.exit(1); } else { await updateExistingEnvVariable("DEVDB_TOKEN", sessionToken); + process.env.DEVDB_TOKEN = sessionToken; console.log("✅ Successfully authenticated the token"); } } catch (error) { diff --git a/cli/src/utils/getCredentials.ts b/cli/src/utils/getCredentials.ts index 3e0ebb7..4d6d68b 100644 --- a/cli/src/utils/getCredentials.ts +++ b/cli/src/utils/getCredentials.ts @@ -1,3 +1,3 @@ -export async function GetCredentials(baseUrl: string, sessionToken: string) { +export function GetCredentials(sessionToken: string) { return `next-auth.session-token=${sessionToken}`; }