|  | 
| 4 | 4 |  */ | 
| 5 | 5 | 
 | 
| 6 | 6 | import { Command } from "@oclif/core"; | 
| 7 |  | -import chalk from "chalk"; | 
| 8 |  | -import * as fs from "../../util/fs.js"; | 
| 9 | 7 | import * as http from "node:http"; | 
| 10 | 8 | import { URL } from "node:url"; | 
| 11 | 9 | import open from "open"; | 
| 12 |  | -import { execSync } from "child_process"; | 
| 13 |  | -import path from "path"; | 
| 14 |  | - | 
| 15 |  | -import { ciStr } from "../../util/ci.js"; | 
| 16 |  | -import { getProjectsByOrgReq, sendMapRepoAndFinishProjectCreationReq, sendCreateProjectReq, sendGetRepoIdReq } from "../../util/graphql.js"; | 
| 17 |  | -import { confirmExistingProjectLink, confirmOverwriteCiHypFile, fileExists, getCiHypFilePath, getSettingsFilePath, getGitConfigFilePath, getGitRemoteUrl, getGithubWorkflowDir, promptProjectLinkSelection, promptProjectName, readSettingsJson, writeGithubInstallationIdToSettingsFile } from "../../util/index.js"; | 
| 18 | 10 | 
 | 
| 19 | 11 | export default class LinkIndex extends Command { | 
|  | 12 | +  static override hidden = true; | 
|  | 13 | + | 
| 20 | 14 |   static override args = {}; | 
| 21 | 15 | 
 | 
| 22 |  | -  static override description = "Link a repo with a Modus App to a Hypermode Project"; | 
|  | 16 | +  // static override description = "Link a repo with a Modus App to a Hypermode Project"; | 
|  | 17 | +  static override description = "Temporarily disabled during migration"; | 
| 23 | 18 | 
 | 
| 24 | 19 |   static override examples = ["<%= config.bin %> <%= command.id %>"]; | 
| 25 | 20 | 
 | 
| @@ -100,135 +95,138 @@ export default class LinkIndex extends Command { | 
| 100 | 95 |   } | 
| 101 | 96 | 
 | 
| 102 | 97 |   public async run(): Promise<void> { | 
| 103 |  | -    // 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 | 
| 104 |  | -    const gitConfigFilePath = getGitConfigFilePath(); | 
| 105 |  | - | 
| 106 |  | -    if (!(await fileExists(gitConfigFilePath))) { | 
| 107 |  | -      throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); | 
| 108 |  | -    } | 
| 109 |  | - | 
| 110 |  | -    // Check if the current branch is 'main' | 
| 111 |  | -    let currentBranch = ""; | 
| 112 |  | -    try { | 
| 113 |  | -      currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); | 
| 114 |  | -    } catch (error) { | 
| 115 |  | -      this.log(chalk.red("Unable to determine the current branch.")); | 
| 116 |  | -      throw error; | 
| 117 |  | -    } | 
| 118 |  | - | 
| 119 |  | -    if (currentBranch !== "main") { | 
| 120 |  | -      this.log(chalk.red("You must be on the 'main' branch to link your repository.")); | 
| 121 |  | -      this.log("Please switch to the 'main' branch:"); | 
| 122 |  | -      this.log(`  > ${chalk.blue("git checkout main")}`); | 
| 123 |  | -      this.log("or rename your current branch to 'main'."); | 
| 124 |  | -      this.log(`  > ${chalk.blue("git branch -m main")}`); | 
| 125 |  | -      this.exit(1); | 
| 126 |  | -    } | 
| 127 |  | - | 
| 128 |  | -    const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); | 
| 129 |  | - | 
| 130 |  | -    if (!remoteUrl) { | 
| 131 |  | -      this.log(chalk.red("`hyp link` requires a git remote to work")); | 
| 132 |  | -      const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); | 
| 133 |  | -      const projectName = path.basename(gitRoot); | 
| 134 |  | -      this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); | 
| 135 |  | -      this.log(`And push your code:`); | 
| 136 |  | -      this.log(`  > ${chalk.blue("git remote add origin <GIT_URL>)")}`); | 
| 137 |  | -      this.log(`  > ${chalk.blue("git push -u origin main")}`); | 
| 138 |  | - | 
| 139 |  | -      this.exit(1); | 
| 140 |  | -    } | 
| 141 |  | - | 
| 142 |  | -    // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, | 
| 143 |  | -    // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json | 
| 144 |  | - | 
| 145 |  | -    const settingsFilePath = getSettingsFilePath(); | 
| 146 |  | -    if (!(await fileExists(settingsFilePath))) { | 
| 147 |  | -      this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); | 
| 148 |  | -      return; | 
| 149 |  | -    } | 
| 150 |  | - | 
| 151 |  | -    const settings = await readSettingsJson(settingsFilePath); | 
| 152 |  | - | 
| 153 |  | -    if (!settings.email || !settings.jwt || !settings.orgId) { | 
| 154 |  | -      this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); | 
| 155 |  | -      return; | 
| 156 |  | -    } | 
| 157 |  | - | 
| 158 |  | -    const { gitOwner, repoName } = parseGitUrl(remoteUrl); | 
| 159 |  | - | 
| 160 |  | -    const repoFullName = `${gitOwner}/${repoName}`; | 
| 161 |  | - | 
| 162 |  | -    let installationId = null; | 
| 163 |  | - | 
| 164 |  | -    if (!settings.installationIds || !settings.installationIds[gitOwner]) { | 
| 165 |  | -      installationId = await this.getUserInstallationThroughAuthFlow(); | 
| 166 |  | -      await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); | 
| 167 |  | -    } else { | 
| 168 |  | -      installationId = settings.installationIds[gitOwner]; | 
| 169 |  | -    } | 
| 170 |  | - | 
| 171 |  | -    // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error | 
| 172 |  | -    const repoId = await sendGetRepoIdReq(settings.jwt, installationId, remoteUrl); | 
| 173 |  | - | 
| 174 |  | -    if (!repoId) { | 
| 175 |  | -      throw new Error("No repoId found for the given installationId and gitUrl"); | 
| 176 |  | -    } | 
| 177 |  | - | 
| 178 |  | -    // 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. | 
| 179 |  | -    // 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 | 
| 180 |  | -    const projects = await getProjectsByOrgReq(settings.jwt, settings.orgId); | 
| 181 |  | - | 
| 182 |  | -    const projectsNoRepoId = projects.filter((project) => !project.repoId); | 
| 183 |  | - | 
| 184 |  | -    let selectedProject = null; | 
| 185 |  | - | 
| 186 |  | -    if (projectsNoRepoId.length > 0) { | 
| 187 |  | -      const confirmExistingProject = await confirmExistingProjectLink(); | 
| 188 |  | - | 
| 189 |  | -      if (confirmExistingProject) { | 
| 190 |  | -        selectedProject = await promptProjectLinkSelection(projectsNoRepoId); | 
| 191 |  | -        const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.jwt, selectedProject.id, repoId, repoFullName); | 
| 192 |  | - | 
| 193 |  | -        this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); | 
| 194 |  | -      } else { | 
| 195 |  | -        const projectName = await promptProjectName(projects); | 
| 196 |  | -        const newProject = await sendCreateProjectReq(settings.jwt, settings.orgId, projectName, repoId, repoFullName); | 
| 197 |  | - | 
| 198 |  | -        this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); | 
| 199 |  | -      } | 
| 200 |  | -    } else { | 
| 201 |  | -      const projectName = await promptProjectName(projects); | 
| 202 |  | -      const newProject = await sendCreateProjectReq(settings.jwt, settings.orgId, projectName, repoId, repoFullName); | 
| 203 |  | - | 
| 204 |  | -      this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); | 
| 205 |  | -    } | 
| 206 |  | - | 
| 207 |  | -    // add ci workflow to the repo if it doesn't already exist | 
| 208 |  | -    const githubWorkflowDir = getGithubWorkflowDir(); | 
| 209 |  | -    const ciHypFilePath = getCiHypFilePath(); | 
| 210 |  | - | 
| 211 |  | -    if (!(await fileExists(githubWorkflowDir))) { | 
| 212 |  | -      // create the directory | 
| 213 |  | -      await fs.mkdir(githubWorkflowDir, { recursive: true }); | 
| 214 |  | -    } | 
| 215 |  | - | 
| 216 |  | -    let shouldCreateCIFile = true; | 
| 217 |  | -    if (await fileExists(ciHypFilePath)) { | 
| 218 |  | -      // prompt if they want to replace it | 
| 219 |  | -      const confirmOverwrite = await confirmOverwriteCiHypFile(); | 
| 220 |  | -      if (!confirmOverwrite) { | 
| 221 |  | -        this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); | 
| 222 |  | -        shouldCreateCIFile = false; | 
| 223 |  | -      } | 
| 224 |  | -    } | 
|  | 98 | +    this.error("Temporarily disabled during migration"); | 
|  | 99 | +    return; | 
|  | 100 | + | 
|  | 101 | +    // // 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 | 
|  | 102 | +    // const gitConfigFilePath = getGitConfigFilePath(); | 
|  | 103 | + | 
|  | 104 | +    // if (!(await fileExists(gitConfigFilePath))) { | 
|  | 105 | +    //   throw new Error(chalk.red("No .git found in this directory. Please initialize a git repository with `git init`.")); | 
|  | 106 | +    // } | 
|  | 107 | + | 
|  | 108 | +    // // Check if the current branch is 'main' | 
|  | 109 | +    // let currentBranch = ""; | 
|  | 110 | +    // try { | 
|  | 111 | +    //   currentBranch = execSync("git symbolic-ref --short HEAD", { encoding: "utf-8" }).trim(); | 
|  | 112 | +    // } catch (error) { | 
|  | 113 | +    //   this.log(chalk.red("Unable to determine the current branch.")); | 
|  | 114 | +    //   throw error; | 
|  | 115 | +    // } | 
|  | 116 | + | 
|  | 117 | +    // if (currentBranch !== "main") { | 
|  | 118 | +    //   this.log(chalk.red("You must be on the 'main' branch to link your repository.")); | 
|  | 119 | +    //   this.log("Please switch to the 'main' branch:"); | 
|  | 120 | +    //   this.log(`  > ${chalk.blue("git checkout main")}`); | 
|  | 121 | +    //   this.log("or rename your current branch to 'main'."); | 
|  | 122 | +    //   this.log(`  > ${chalk.blue("git branch -m main")}`); | 
|  | 123 | +    //   this.exit(1); | 
|  | 124 | +    // } | 
|  | 125 | + | 
|  | 126 | +    // const remoteUrl = await getGitRemoteUrl(gitConfigFilePath); | 
|  | 127 | + | 
|  | 128 | +    // if (!remoteUrl) { | 
|  | 129 | +    //   this.log(chalk.red("`hyp link` requires a git remote to work")); | 
|  | 130 | +    //   const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); | 
|  | 131 | +    //   const projectName = path.basename(gitRoot); | 
|  | 132 | +    //   this.log(`Please create a GitHub repository: https://github.com/new?name=${projectName}`); | 
|  | 133 | +    //   this.log(`And push your code:`); | 
|  | 134 | +    //   this.log(`  > ${chalk.blue("git remote add origin <GIT_URL>)")}`); | 
|  | 135 | +    //   this.log(`  > ${chalk.blue("git push -u origin main")}`); | 
|  | 136 | + | 
|  | 137 | +    //   this.exit(1); | 
|  | 138 | +    // } | 
|  | 139 | + | 
|  | 140 | +    // // check the .hypermode/settings.json and see if there is a installationId with a key for the github owner. if there is, | 
|  | 141 | +    // // continue, if not send them to github app installation page, and then go to callback server, and add installation id to settings.json | 
|  | 142 | + | 
|  | 143 | +    // const settingsFilePath = getSettingsFilePath(); | 
|  | 144 | +    // if (!(await fileExists(settingsFilePath))) { | 
|  | 145 | +    //   this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); | 
|  | 146 | +    //   return; | 
|  | 147 | +    // } | 
|  | 148 | + | 
|  | 149 | +    // const settings = await readSettingsJson(settingsFilePath); | 
|  | 150 | + | 
|  | 151 | +    // if (!settings.email || !settings.apiKey || !settings.orgId) { | 
|  | 152 | +    //   this.log(chalk.red("Not logged in.") + " Log in with `hyp login`."); | 
|  | 153 | +    //   return; | 
|  | 154 | +    // } | 
|  | 155 | + | 
|  | 156 | +    // const { gitOwner, repoName } = parseGitUrl(remoteUrl); | 
|  | 157 | + | 
|  | 158 | +    // const repoFullName = `${gitOwner}/${repoName}`; | 
|  | 159 | + | 
|  | 160 | +    // let installationId = null; | 
|  | 161 | + | 
|  | 162 | +    // if (!settings.installationIds || !settings.installationIds[gitOwner]) { | 
|  | 163 | +    //   installationId = await this.getUserInstallationThroughAuthFlow(); | 
|  | 164 | +    //   await writeGithubInstallationIdToSettingsFile(gitOwner, installationId); | 
|  | 165 | +    // } else { | 
|  | 166 | +    //   installationId = settings.installationIds[gitOwner]; | 
|  | 167 | +    // } | 
|  | 168 | + | 
|  | 169 | +    // // call hypermode getRepoId with the installationId and the git url, if it returns a repoId, continue, if not, throw an error | 
|  | 170 | +    // const repoId = await sendGetRepoIdReq(settings.apiKey, installationId, remoteUrl); | 
|  | 171 | + | 
|  | 172 | +    // if (!repoId) { | 
|  | 173 | +    //   throw new Error("No repoId found for the given installationId and gitUrl"); | 
|  | 174 | +    // } | 
|  | 175 | + | 
|  | 176 | +    // // 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. | 
|  | 177 | +    // // 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 | 
|  | 178 | +    // const projects = await getProjectsByOrgReq(settings.apiKey, settings.orgId); | 
|  | 179 | + | 
|  | 180 | +    // const projectsNoRepoId = projects.filter((project) => !project.repoId); | 
|  | 181 | + | 
|  | 182 | +    // let selectedProject = null; | 
|  | 183 | + | 
|  | 184 | +    // if (projectsNoRepoId.length > 0) { | 
|  | 185 | +    //   const confirmExistingProject = await confirmExistingProjectLink(); | 
|  | 186 | + | 
|  | 187 | +    //   if (confirmExistingProject) { | 
|  | 188 | +    //     selectedProject = await promptProjectLinkSelection(projectsNoRepoId); | 
|  | 189 | +    //     const completedProject = await sendMapRepoAndFinishProjectCreationReq(settings.apiKey, selectedProject.id, repoId, repoFullName); | 
|  | 190 | + | 
|  | 191 | +    //     this.log(chalk.green("Successfully linked project " + completedProject.name + " to repo " + repoName + "! 🎉")); | 
|  | 192 | +    //   } else { | 
|  | 193 | +    //     const projectName = await promptProjectName(projects); | 
|  | 194 | +    //     const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); | 
|  | 195 | + | 
|  | 196 | +    //     this.log(chalk.green("Successfully created project " + newProject.name + " and linked it to repo " + repoName + "! 🎉")); | 
|  | 197 | +    //   } | 
|  | 198 | +    // } else { | 
|  | 199 | +    //   const projectName = await promptProjectName(projects); | 
|  | 200 | +    //   const newProject = await sendCreateProjectReq(settings.apiKey, settings.orgId, projectName, repoId, repoFullName); | 
|  | 201 | + | 
|  | 202 | +    //   this.log(chalk.blueBright("Successfully created project " + newProject.name + " and linked it to repo " + repoFullName + "! Setting up CI workflow...")); | 
|  | 203 | +    // } | 
|  | 204 | + | 
|  | 205 | +    // // add ci workflow to the repo if it doesn't already exist | 
|  | 206 | +    // const githubWorkflowDir = getGithubWorkflowDir(); | 
|  | 207 | +    // const ciHypFilePath = getCiHypFilePath(); | 
|  | 208 | + | 
|  | 209 | +    // if (!(await fileExists(githubWorkflowDir))) { | 
|  | 210 | +    //   // create the directory | 
|  | 211 | +    //   await fs.mkdir(githubWorkflowDir, { recursive: true }); | 
|  | 212 | +    // } | 
|  | 213 | + | 
|  | 214 | +    // let shouldCreateCIFile = true; | 
|  | 215 | +    // if (await fileExists(ciHypFilePath)) { | 
|  | 216 | +    //   // prompt if they want to replace it | 
|  | 217 | +    //   const confirmOverwrite = await confirmOverwriteCiHypFile(); | 
|  | 218 | +    //   if (!confirmOverwrite) { | 
|  | 219 | +    //     this.log(chalk.yellow("Skipping ci-modus-build.yml creation.")); | 
|  | 220 | +    //     shouldCreateCIFile = false; | 
|  | 221 | +    //   } | 
|  | 222 | +    // } | 
| 225 | 223 | 
 | 
| 226 |  | -    if (shouldCreateCIFile) { | 
| 227 |  | -      await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); | 
| 228 |  | -      this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); | 
| 229 |  | -    } | 
| 230 |  | - | 
| 231 |  | -    this.log(chalk.green("Linking complete! 🎉")); | 
|  | 224 | +    // if (shouldCreateCIFile) { | 
|  | 225 | +    //   await fs.writeFile(ciHypFilePath, ciStr, { flag: "w" }); | 
|  | 226 | +    //   this.log(chalk.green("Modus CI workflow added to your project. Commit this change to initiate a deployment to Hypermode.")); | 
|  | 227 | +    // } | 
|  | 228 | + | 
|  | 229 | +    // this.log(chalk.green("Linking complete! 🎉")); | 
| 232 | 230 |   } | 
| 233 | 231 | } | 
| 234 | 232 | 
 | 
| @@ -284,16 +282,16 @@ const linkHTML = `<!-- src/commands/login/login.html --> | 
| 284 | 282 | </html> | 
| 285 | 283 | `; | 
| 286 | 284 | 
 | 
| 287 |  | -function parseGitUrl(gitUrl: string) { | 
| 288 |  | -  const regex = /^(?:git@|https:\/\/)([^:/]+)[:/]([^/]+)\/([^/]+?)(?:\.git)?$/; | 
| 289 |  | -  const match = gitUrl.match(regex); | 
|  | 285 | +// function parseGitUrl(gitUrl: string) { | 
|  | 286 | +//   const regex = /^(?:git@|https:\/\/)([^:/]+)[:/]([^/]+)\/([^/]+?)(?:\.git)?$/; | 
|  | 287 | +//   const match = gitUrl.match(regex); | 
| 290 | 288 | 
 | 
| 291 |  | -  if (!match) { | 
| 292 |  | -    throw new Error(`Invalid Git URL: ${gitUrl}`); | 
| 293 |  | -  } | 
|  | 289 | +//   if (!match) { | 
|  | 290 | +//     throw new Error(`Invalid Git URL: ${gitUrl}`); | 
|  | 291 | +//   } | 
| 294 | 292 | 
 | 
| 295 |  | -  const gitOwner = match[2]; | 
| 296 |  | -  const repoName = match[3]; | 
|  | 293 | +//   const gitOwner = match[2]; | 
|  | 294 | +//   const repoName = match[3]; | 
| 297 | 295 | 
 | 
| 298 |  | -  return { gitOwner, repoName }; | 
| 299 |  | -} | 
|  | 296 | +//   return { gitOwner, repoName }; | 
|  | 297 | +// } | 
0 commit comments