diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index d5c2bc1..b491240 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -18,19 +18,19 @@ runtimes: # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) lint: enabled: - - trivy@0.59.1 + - trivy@0.60.0 - actionlint@1.7.7 - - checkov@3.2.365 - - eslint@9.19.0 + - checkov@3.2.386 + - eslint@9.22.0 - git-diff-check - markdownlint@0.44.0 - - osv-scanner@1.9.2 - - prettier@3.4.2 - - renovate@39.161.0 + - osv-scanner@2.0.0 + - prettier@3.5.3 + - renovate@39.207.2 - shellcheck@0.10.0 - shfmt@3.6.0 - - trufflehog@3.88.4 - - yamllint@1.35.1 + - trufflehog@3.88.17 + - yamllint@1.36.2 actions: enabled: - trunk-announce diff --git a/.vscode/settings.json b/.vscode/settings.json index 93ff3ac..1e49ba9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,8 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "trunk.io", "editor.trimAutoWhitespace": true, - "trunk.autoInit": false + "trunk.autoInit": false, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/src/commands/link/index.ts b/src/commands/link/index.ts index 0cc8abb..21aaca6 100644 --- a/src/commands/link/index.ts +++ b/src/commands/link/index.ts @@ -4,22 +4,17 @@ */ import { Command } from "@oclif/core"; -import chalk from "chalk"; -import * as fs from "../../util/fs.js"; import * as http from "node:http"; import { URL } from "node:url"; import open from "open"; -import { execSync } from "child_process"; -import path from "path"; - -import { ciStr } from "../../util/ci.js"; -import { getProjectsByOrgReq, sendMapRepoAndFinishProjectCreationReq, sendCreateProjectReq, sendGetRepoIdReq } from "../../util/graphql.js"; -import { confirmExistingProjectLink, confirmOverwriteCiHypFile, fileExists, getCiHypFilePath, getSettingsFilePath, getGitConfigFilePath, getGitRemoteUrl, getGithubWorkflowDir, promptProjectLinkSelection, promptProjectName, readSettingsJson, writeGithubInstallationIdToSettingsFile } from "../../util/index.js"; export default class LinkIndex extends Command { + static override hidden = true; + static override args = {}; - static override description = "Link a repo with a Modus App to a Hypermode Project"; + // static override description = "Link a repo with a Modus App to a Hypermode Project"; + static override description = "Temporarily disabled during migration"; static override examples = ["<%= config.bin %> <%= command.id %>"]; @@ -100,135 +95,138 @@ export default class LinkIndex extends Command { } public async run(): Promise { - // check if the directory has a .git/config with a remote named 'origin', if not, throw an error and ask them to set that up - const gitConfigFilePath = getGitConfigFilePath(); - - if (!(await fileExists(gitConfigFilePath))) { - throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); - } - - // Check if the current branch is 'main' - let currentBranch = ""; - try { - currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); - } catch (error) { - this.log(chalk.red("Unable to determine the current branch.")); - throw error; - } - - if (currentBranch !== "main") { - this.log(chalk.red("You must be on the 'main' branch to link your repository.")); - this.log("Please switch to the 'main' branch:"); - this.log(` > ${chalk.blue("git checkout main")}`); - this.log("or rename your current branch to 'main'."); - this.log(` > ${chalk.blue("git branch -m main")}`); - this.exit(1); - } - - const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); - - if (!remoteUrl) { - this.log(chalk.red("`hyp link` requires a git remote to work")); - const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); - const projectName = path.basename(gitRoot); - this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); - this.log(`And push your code:`); - this.log(` > ${chalk.blue("git remote add origin )")}`); - this.log(` > ${chalk.blue("git push -u origin main")}`); - - this.exit(1); - } - - // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, - // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json - - const settingsFilePath = getSettingsFilePath(); - if (!(await fileExists(settingsFilePath))) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } - - const settings = await readSettingsJson(settingsFilePath); - - if (!settings.email || !settings.jwt || !settings.orgId) { - this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); - return; - } - - const { gitOwner, repoName } = parseGitUrl(remoteUrl); - - const repoFullName = `${gitOwner}/${repoName}`; - - let installationId = null; - - if (!settings.installationIds || !settings.installationIds[gitOwner]) { - installationId = await this.getUserInstallationThroughAuthFlow(); - await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); - } else { - installationId = settings.installationIds[gitOwner]; - } - - // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error - const repoId = await sendGetRepoIdReq(settings.jwt, installationId, remoteUrl); - - if (!repoId) { - throw new Error("No repoId found for the given installationId and gitUrl"); - } - - // get list of the projects for the user in this org, if any have no repoId, ask if they want to link it, or give option of none. - // If they pick an option, connect repo. If none, ask if they want to create a new project, prompt for name, and connect repoId to project - const projects = await getProjectsByOrgReq(settings.jwt, settings.orgId); - - const projectsNoRepoId = projects.filter((project) => !project.repoId); - - let selectedProject = null; - - if (projectsNoRepoId.length > 0) { - const confirmExistingProject = await confirmExistingProjectLink(); - - if (confirmExistingProject) { - selectedProject = await promptProjectLinkSelection(projectsNoRepoId); - const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.jwt, selectedProject.id, repoId, repoFullName); - - this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); - } else { - const projectName = await promptProjectName(projects); - const newProject = await sendCreateProjectReq(settings.jwt, settings.orgId, projectName, repoId, repoFullName); - - this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); - } - } else { - const projectName = await promptProjectName(projects); - const newProject = await sendCreateProjectReq(settings.jwt, settings.orgId, projectName, repoId, repoFullName); - - this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); - } - - // add ci workflow to the repo if it doesn't already exist - const githubWorkflowDir = getGithubWorkflowDir(); - const ciHypFilePath = getCiHypFilePath(); - - if (!(await fileExists(githubWorkflowDir))) { - // create the directory - await fs.mkdir(githubWorkflowDir, { recursive: true }); - } - - let shouldCreateCIFile = true; - if (await fileExists(ciHypFilePath)) { - // prompt if they want to replace it - const confirmOverwrite = await confirmOverwriteCiHypFile(); - if (!confirmOverwrite) { - this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); - shouldCreateCIFile = false; - } - } + this.error("Temporarily disabled during migration"); + return; + + // // check if the directory has a .git/config with a remote named 'origin', if not, throw an error and ask them to set that up + // const gitConfigFilePath = getGitConfigFilePath(); + + // if (!(await fileExists(gitConfigFilePath))) { + // throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); + // } + + // // Check if the current branch is 'main' + // let currentBranch = ""; + // try { + // currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); + // } catch (error) { + // this.log(chalk.red("Unable to determine the current branch.")); + // throw error; + // } + + // if (currentBranch !== "main") { + // this.log(chalk.red("You must be on the 'main' branch to link your repository.")); + // this.log("Please switch to the 'main' branch:"); + // this.log(` > ${chalk.blue("git checkout main")}`); + // this.log("or rename your current branch to 'main'."); + // this.log(` > ${chalk.blue("git branch -m main")}`); + // this.exit(1); + // } + + // const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); + + // if (!remoteUrl) { + // this.log(chalk.red("`hyp link` requires a git remote to work")); + // const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); + // const projectName = path.basename(gitRoot); + // this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); + // this.log(`And push your code:`); + // this.log(` > ${chalk.blue("git remote add origin )")}`); + // this.log(` > ${chalk.blue("git push -u origin main")}`); + + // this.exit(1); + // } + + // // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, + // // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json + + // const settingsFilePath = getSettingsFilePath(); + // if (!(await fileExists(settingsFilePath))) { + // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + // return; + // } + + // const settings = await readSettingsJson(settingsFilePath); + + // if (!settings.email || !settings.apiKey || !settings.orgId) { + // this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); + // return; + // } + + // const { gitOwner, repoName } = parseGitUrl(remoteUrl); + + // const repoFullName = `${gitOwner}/${repoName}`; + + // let installationId = null; + + // if (!settings.installationIds || !settings.installationIds[gitOwner]) { + // installationId = await this.getUserInstallationThroughAuthFlow(); + // await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); + // } else { + // installationId = settings.installationIds[gitOwner]; + // } + + // // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error + // const repoId = await sendGetRepoIdReq(settings.apiKey, installationId, remoteUrl); + + // if (!repoId) { + // throw new Error("No repoId found for the given installationId and gitUrl"); + // } + + // // get list of the projects for the user in this org, if any have no repoId, ask if they want to link it, or give option of none. + // // If they pick an option, connect repo. If none, ask if they want to create a new project, prompt for name, and connect repoId to project + // const projects = await getProjectsByOrgReq(settings.apiKey, settings.orgId); + + // const projectsNoRepoId = projects.filter((project) => !project.repoId); + + // let selectedProject = null; + + // if (projectsNoRepoId.length > 0) { + // const confirmExistingProject = await confirmExistingProjectLink(); + + // if (confirmExistingProject) { + // selectedProject = await promptProjectLinkSelection(projectsNoRepoId); + // const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.apiKey, selectedProject.id, repoId, repoFullName); + + // this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); + // } else { + // const projectName = await promptProjectName(projects); + // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); + + // this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); + // } + // } else { + // const projectName = await promptProjectName(projects); + // const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); + + // this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); + // } + + // // add ci workflow to the repo if it doesn't already exist + // const githubWorkflowDir = getGithubWorkflowDir(); + // const ciHypFilePath = getCiHypFilePath(); + + // if (!(await fileExists(githubWorkflowDir))) { + // // create the directory + // await fs.mkdir(githubWorkflowDir, { recursive: true }); + // } + + // let shouldCreateCIFile = true; + // if (await fileExists(ciHypFilePath)) { + // // prompt if they want to replace it + // const confirmOverwrite = await confirmOverwriteCiHypFile(); + // if (!confirmOverwrite) { + // this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); + // shouldCreateCIFile = false; + // } + // } - if (shouldCreateCIFile) { - await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); - this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); - } - - this.log(chalk.green("Linking complete! 🎉")); + // if (shouldCreateCIFile) { + // await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); + // this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); + // } + + // this.log(chalk.green("Linking complete! 🎉")); } } @@ -284,16 +282,16 @@ const linkHTML = ` `; -function parseGitUrl(gitUrl: string) { - const regex = /^(?:git@|https:\/\/)([^:/]+)[:/]([^/]+)\/([^/]+?)(?:\.git)?$/; - const match = gitUrl.match(regex); +// function parseGitUrl(gitUrl: string) { +// const regex = /^(?:git@|https:\/\/)([^:/]+)[:/]([^/]+)\/([^/]+?)(?:\.git)?$/; +// const match = gitUrl.match(regex); - if (!match) { - throw new Error(`Invalid Git URL: ${gitUrl}`); - } +// if (!match) { +// throw new Error(`Invalid Git URL: ${gitUrl}`); +// } - const gitOwner = match[2]; - const repoName = match[3]; +// const gitOwner = match[2]; +// const repoName = match[3]; - return { gitOwner, repoName }; -} +// return { gitOwner, repoName }; +// } diff --git a/src/commands/login/index.ts b/src/commands/login/index.ts index 33dccc2..cc66a2d 100644 --- a/src/commands/login/index.ts +++ b/src/commands/login/index.ts @@ -75,7 +75,7 @@ export default class LoginIndex extends Command { public async openLoginPage() { // Open the Hypermode sign-in page in the default browser - const loginUrl = "https://hypermode.com/app/callback?port=5051&type=cli"; + const loginUrl = "http://localhost:3000/callback?port=5051&type=cli"; await open(loginUrl); } @@ -86,13 +86,35 @@ export default class LoginIndex extends Command { const url = new URL(req.url ?? "", `http://${req.headers.host}`); const jwt = url.searchParams.get("jwt"); const email = url.searchParams.get("email"); + const userId = url.searchParams.get("user"); - if (!jwt || !email) { + if (!jwt || !email || !userId) { res.writeHead(400, { "Content-Type": "text/plain" }); - res.end("JWT or email not found in the request."); + res.end("JWT, email, or userID not found in the request."); return; } + const response = await fetch("http://localhost:3000/api/api-key/create", { + method: "POST", + headers: { + Authorization: `Bearer ${jwt}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userId, + name: "CLI Access Key", + expiresIn: 60 * 60 * 24 * 7, // 7 days + prefix: "cli", + }), + }); + + const { data, error } = await response.json(); + const apiKey = data.key; + + if (!apiKey || error) { + throw new Error(error); + } + res.writeHead(200, { "Content-Type": "text/html" }); res.end(loginHTML); @@ -107,9 +129,9 @@ export default class LoginIndex extends Command { } try { - const orgs = await sendGetOrgsReq(jwt); + const orgs = await sendGetOrgsReq(apiKey); const selectedOrg = await promptOrgSelection(orgs); - await writeToSettingsFile(jwt, email, selectedOrg.id); + await writeToSettingsFile(apiKey, email, selectedOrg.workspaces[0].id); this.log("Successfully logged in as " + chalk.dim(email) + "! 🎉"); resolve(); } catch (error) { diff --git a/src/commands/logout/index.ts b/src/commands/logout/index.ts index 556b313..e22ea94 100644 --- a/src/commands/logout/index.ts +++ b/src/commands/logout/index.ts @@ -38,7 +38,7 @@ export default class LogoutIndex extends Command { const newSettingsContent = { HYP_EMAIL: null, - HYP_JWT: null, + HYP_API_KEY: null, HYP_ORG_ID: null, INSTALLATION_IDS: res.installationIds, }; diff --git a/src/commands/org/switch.ts b/src/commands/org/switch.ts index 3c87b92..e26562b 100644 --- a/src/commands/org/switch.ts +++ b/src/commands/org/switch.ts @@ -10,6 +10,7 @@ import { sendGetOrgsReq } from "../../util/graphql.js"; import { fileExists, getSettingsFilePath, promptOrgSelection, readSettingsJson, writeToSettingsFile } from "../../util/index.js"; export default class OrgSwitch extends Command { + static override hidden = true; static override args = {}; static override description = "Switch the current Hypermode organization"; @@ -27,14 +28,14 @@ export default class OrgSwitch extends Command { const res = await readSettingsJson(settingsFilePath); - if (!res.email || !res.jwt || !res.orgId) { + if (!res.email || !res.apiKey || !res.workspaceId) { this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); return; } - const orgs = await sendGetOrgsReq(res.jwt); + const orgs = await sendGetOrgsReq(res.apiKey); const selectedOrg = await promptOrgSelection(orgs); - await writeToSettingsFile(res.jwt, res.email, selectedOrg.id); + await writeToSettingsFile(res.apiKey, res.email, selectedOrg.id); } } diff --git a/src/util/graphql.ts b/src/util/graphql.ts index 80d7fdc..11fc076 100644 --- a/src/util/graphql.ts +++ b/src/util/graphql.ts @@ -3,17 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Org, Project } from "../util/types.js"; +import { Org, App } from "../util/types.js"; import { getSlugFromName } from "./index.js"; import chalk from "chalk"; -export async function sendGraphQLReqToHypermode(jwt: string, query: string): Promise { - const url = "https://api.hypermode.com/graphql"; +export async function sendGraphQLReqToHypermode(apiKey: string, query: string): Promise { + const url = "http://localhost:9081/graphql"; const options = { body: JSON.stringify({ query }), headers: { - Authorization: `${jwt}`, + "X-API-Key": apiKey, "Content-Type": "application/json", }, method: "POST", @@ -25,7 +25,7 @@ export async function sendGraphQLReqToHypermode(jwt: string, query: string): Pro if (!response.ok) { if (response.status === 401) { console.error(`Unauthorized. Please try ${chalk.blueBright("hyp login")} again.`); - throw new Error("Unauthorized: Invalid or expired JWT token."); + throw new Error("Unauthorized: Invalid or expired API key."); } else { throw new Error(`HTTP Error: ${response.status} ${response.statusText}`); } @@ -38,7 +38,35 @@ export async function sendGraphQLReqToHypermode(jwt: string, query: string): Pro } } -export async function sendMapRepoAndFinishProjectCreationReq(jwt: string, id: string, repoId: string, repoName: string): Promise { +/** + * Queries working with new Data Model + */ +export async function sendGetOrgsReq(apiKey: string): Promise { + const query = ` + query GetOrgs { + getOrgs { + id + slug + workspaces { + id + name + slug + } + } + }`; + + const data: any = await sendGraphQLReqToHypermode(apiKey, query); + + const orgs: Org[] = data.data.getOrgs; + + return orgs; +} + +/** + * Queries not yet working with new Data Model + */ + +export async function sendMapRepoAndFinishProjectCreationReq(apiKey: string, id: string, repoId: string, repoName: string): Promise { const query = ` mutation MapRepoAndFinishProjectCreation { mapRepoAndFinishProjectCreation(input: {id: "${id}", repoName: "${repoName}", repoId: "${repoId}", sourceType: CUSTOM, defaultBranchName: "main"}) { @@ -48,14 +76,14 @@ export async function sendMapRepoAndFinishProjectCreationReq(jwt: string, id: st } }`; - const data: any = await sendGraphQLReqToHypermode(jwt, query); + const data: any = await sendGraphQLReqToHypermode(apiKey, query); - const project: Project = data.data.mapRepoAndFinishProjectCreation; + const project: App = data.data.mapRepoAndFinishProjectCreation; return project; } -export async function sendCreateProjectReq(jwt: string, orgId: string, projectName: string, repoId: string, repoName: string): Promise { +export async function sendCreateProjectReq(apiKey: string, orgId: string, projectName: string, repoId: string, repoName: string): Promise { const slug = getSlugFromName(projectName); const query = ` mutation CreateProjectBranchRuntime { @@ -67,30 +95,14 @@ export async function sendCreateProjectReq(jwt: string, orgId: string, projectNa } }`; - const res: any = await sendGraphQLReqToHypermode(jwt, query); + const res: any = await sendGraphQLReqToHypermode(apiKey, query); - const project: Project = res.data.createProjectBranchRuntime; + const project: App = res.data.createProjectBranchRuntime; return project; } -export async function sendGetOrgsReq(jwt: string): Promise { - const query = ` - query GetOrgs { - getOrgs { - id - slug - } - }`; - - const data: any = await sendGraphQLReqToHypermode(jwt, query); - - const orgs: Org[] = data.data.getOrgs; - - return orgs; -} - -export async function getProjectsByOrgReq(jwt: string, orgId: string): Promise { +export async function getProjectsByOrgReq(apiKey: string, orgId: string): Promise { const query = ` query GetProjectsByOrg { getOrg(id: "${orgId}") { @@ -103,20 +115,20 @@ export async function getProjectsByOrgReq(jwt: string, orgId: string): Promise

{ +export async function sendGetRepoIdReq(apiKey: string, installationId: string, gitUrl: string): Promise { const query = ` query getUserRepoIdByUrl { getUserRepoIdByUrl(installationId: "${installationId}", gitUrl: "${gitUrl}") }`; - const res: any = await sendGraphQLReqToHypermode(jwt, query); + const res: any = await sendGraphQLReqToHypermode(apiKey, query); if (!res.data.getUserRepoIdByUrl) { throw new Error("No repoId found for the given installationId and gitUrl"); diff --git a/src/util/index.ts b/src/util/index.ts index 0de0dfa..c4ee0d0 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -11,7 +11,7 @@ import slugify from "@sindresorhus/slugify"; import * as path from "node:path"; import os from "node:os"; -import { Org, Project } from "../util/types.js"; +import { Org, App } from "../util/types.js"; export async function promptOrgSelection(orgs: Org[]): Promise { const choices = orgs.map((org) => ({ @@ -21,17 +21,17 @@ export async function promptOrgSelection(orgs: Org[]): Promise { try { const selectedOrg = await inquirer.select({ choices, - message: "Please select an organization:", + message: "Please select an workspace:", }); return selectedOrg; } catch (error) { - const error_ = error instanceof ExitPromptError ? new TypeError(chalk.red("Organization selection prompt exited.")) : error; + const error_ = error instanceof ExitPromptError ? new TypeError(chalk.red("Workspace selection prompt exited.")) : error; throw error_; } } -export async function promptProjectLinkSelection(projects: Project[]): Promise { +export async function promptProjectLinkSelection(projects: App[]): Promise { const choices = projects.map((project) => ({ name: project.name, value: project, @@ -49,7 +49,7 @@ export async function promptProjectLinkSelection(projects: Project[]): Promise

{ +export async function promptProjectName(projects: App[]): Promise { const projectName = await inquirer.input({ message: "Creating a new project. Please enter a project name:", }); @@ -132,19 +132,19 @@ export async function getGitRemoteUrl(filePath: string): Promise return remoteMatch[1]; } -export async function readSettingsJson(filePath: string): Promise<{ content: string; email: null | string; installationIds: { [key: string]: string } | null; jwt: null | string; orgId: null | string }> { +export async function readSettingsJson(filePath: string): Promise<{ content: string; email: null | string; installationIds: { [key: string]: string } | null; apiKey: null | string; workspaceId: null | string }> { const content = await fs.readFile(filePath, "utf8"); let email: null | string = null; - let jwt: null | string = null; - let orgId: null | string = null; + let apiKey: null | string = null; + let workspaceId: null | string = null; let installationIds: { [key: string]: string } | null = null; try { const jsonContent = JSON.parse(content); email = jsonContent.HYP_EMAIL || null; - jwt = jsonContent.HYP_JWT || null; - orgId = jsonContent.HYP_ORG_ID || null; + apiKey = jsonContent.HYP_API_KEY || null; + workspaceId = jsonContent.HYP_WORKSPACE_ID || null; installationIds = jsonContent.INSTALLATION_IDS || null; } catch { // ignore error @@ -154,12 +154,12 @@ export async function readSettingsJson(filePath: string): Promise<{ content: str content, email, installationIds, - jwt, - orgId, + apiKey, + workspaceId, }; } -export async function writeToSettingsFile(jwt: string, email: string, orgId: string): Promise { +export async function writeToSettingsFile(apiKey: string, email: string, workspaceId: string): Promise { const settingsDir = getSettingsDir(); const settingsFilePath = getSettingsFilePath(); @@ -168,10 +168,10 @@ export async function writeToSettingsFile(jwt: string, email: string, orgId: str await fs.mkdir(settingsDir, { recursive: true }); } - const newSettingsContent: { HYP_EMAIL: string; HYP_JWT: string; HYP_ORG_ID: string; INSTALLATION_IDS: { [key: string]: string } | null } = { + const newSettingsContent: { HYP_EMAIL: string; HYP_API_KEY: string; HYP_WORKSPACE_ID: string; INSTALLATION_IDS: { [key: string]: string } | null } = { HYP_EMAIL: email, - HYP_JWT: jwt, - HYP_ORG_ID: orgId, + HYP_API_KEY: apiKey, + HYP_WORKSPACE_ID: workspaceId, INSTALLATION_IDS: null, }; @@ -191,12 +191,7 @@ export async function writeGithubInstallationIdToSettingsFile(gitOwner: string, settings.installationIds = settings.installationIds || {}; settings.installationIds[gitOwner] = installationId; - const newSettingsContent = { - HYP_EMAIL: settings.email, - HYP_JWT: settings.jwt, - HYP_ORG_ID: settings.orgId, - INSTALLATION_IDS: settings.installationIds, - }; + const newSettingsContent = { ...settings }; await fs.writeFile(settingsFilePath, JSON.stringify(newSettingsContent, null, 2), { flag: "w" }); } diff --git a/src/util/types.ts b/src/util/types.ts index 55de3be..742abb9 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -5,11 +5,19 @@ export type Org = { id: string; - projects: Project[]; + name: string; + slug: string; + workspaces: Workspace[]; +}; + +export type Workspace = { + id: string; + name: string; slug: string; + apps: App[]; }; -export type Project = { +export type App = { id: string; name: string; repoId: null | string;