connect.ts108 lines · main
| 1 | /** |
| 2 | * `briven connect` — attach an **existing** cloud project to this folder |
| 3 | * (sign in → pick project → CLI key → S3 → local wire). |
| 4 | * |
| 5 | * Brand-new projects use `briven setup` instead. |
| 6 | * |
| 7 | * Subcommands kept for session hygiene: |
| 8 | * briven connect status |
| 9 | * briven connect logout |
| 10 | */ |
| 11 | |
| 12 | import { clearUserCredential, readCredentials, readUserCredential } from '../config.js'; |
| 13 | import { |
| 14 | printConnectProjectHelp, |
| 15 | runConnectProject, |
| 16 | } from '../setup.js'; |
| 17 | import { fetchMe } from '../platform.js'; |
| 18 | import { |
| 19 | banner, |
| 20 | blankLine, |
| 21 | error as printError, |
| 22 | link as printLink, |
| 23 | step, |
| 24 | success, |
| 25 | } from '../output.js'; |
| 26 | import { ApiCallError } from '../api-client.js'; |
| 27 | |
| 28 | export async function runConnect(argv: readonly string[]): Promise<number> { |
| 29 | const [sub] = argv; |
| 30 | |
| 31 | if (sub === '--help' || sub === '-h' || sub === 'help') { |
| 32 | printConnectProjectHelp(); |
| 33 | return 0; |
| 34 | } |
| 35 | |
| 36 | if (sub === 'status') { |
| 37 | return runStatus(); |
| 38 | } |
| 39 | |
| 40 | if (sub === 'logout') { |
| 41 | return runConnectLogout(); |
| 42 | } |
| 43 | |
| 44 | // Full attach path (also accepts `login` as a no-op alias prefix for --force flows). |
| 45 | const attachArgv = |
| 46 | sub === 'login' ? argv.slice(1) : argv; |
| 47 | return runConnectProject(attachArgv); |
| 48 | } |
| 49 | |
| 50 | async function runStatus(): Promise<number> { |
| 51 | banner('connect status'); |
| 52 | blankLine(); |
| 53 | |
| 54 | const user = await readUserCredential(); |
| 55 | if (!user) { |
| 56 | step('platform: not signed in'); |
| 57 | step('run: briven connect'); |
| 58 | } else { |
| 59 | try { |
| 60 | const me = await fetchMe(user.apiOrigin, user.token); |
| 61 | success(`platform: signed in as ${me.email}`); |
| 62 | step(`user id ${me.id}`); |
| 63 | step(`api ${user.apiOrigin}`); |
| 64 | step(`saved at ${user.savedAt}`); |
| 65 | } catch (err) { |
| 66 | if (err instanceof ApiCallError) { |
| 67 | printError(`platform: session invalid (${err.code})`); |
| 68 | } else { |
| 69 | printError(err instanceof Error ? err.message : 'platform: session check failed'); |
| 70 | } |
| 71 | step('run: briven connect'); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | const local = await readCredentials(); |
| 76 | const ids = Object.keys(local.projects); |
| 77 | blankLine(); |
| 78 | if (ids.length === 0) { |
| 79 | step('local projects: none'); |
| 80 | } else { |
| 81 | step(`local projects: ${ids.length}`); |
| 82 | for (const id of ids.sort()) { |
| 83 | const c = local.projects[id]!; |
| 84 | const marker = local.default === id ? '*' : ' '; |
| 85 | step(` ${marker} ${id} ····${c.suffix}`); |
| 86 | } |
| 87 | if (local.default) step(`default: ${local.default}`); |
| 88 | } |
| 89 | |
| 90 | blankLine(); |
| 91 | step('attach an existing project to this folder: briven connect'); |
| 92 | step('create a brand-new project: briven setup my-app'); |
| 93 | printLink('https://docs.briven.tech/connect'); |
| 94 | return 0; |
| 95 | } |
| 96 | |
| 97 | async function runConnectLogout(): Promise<number> { |
| 98 | banner('connect logout'); |
| 99 | const user = await readUserCredential(); |
| 100 | if (!user) { |
| 101 | step('no platform session stored'); |
| 102 | return 0; |
| 103 | } |
| 104 | await clearUserCredential(); |
| 105 | success('platform session cleared (project keys kept)'); |
| 106 | step('to wipe project keys too: briven logout'); |
| 107 | return 0; |
| 108 | } |