@roxyon/cli 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -477,17 +477,24 @@ async function ask2(fn) {
477
477
 
478
478
  // src/commands/token.ts
479
479
  import { RoxyonApiError as RoxyonApiError5 } from "@roxyon/api-client";
480
- var SCOPES = ["deploy", "logs", "read"];
480
+ var SCOPES = ["deploy", "logs", "read", "billing:order"];
481
481
  async function tokenCreate(name, opts) {
482
482
  if (!name) fail("A name is required: roxyon token create <name>", EXIT.configError);
483
483
  const scopes = (opts.scopes ? opts.scopes.split(",") : ["deploy", "logs"]).map((s) => s.trim().toLowerCase()).filter((s) => SCOPES.includes(s));
484
484
  if (scopes.length === 0)
485
485
  fail(`--scopes must be a subset of: ${SCOPES.join(", ")}`, EXIT.configError);
486
+ const ordering = scopes.includes("billing:order");
487
+ if (ordering && !(opts.budget && opts.budget > 0))
488
+ fail("A billing:order token needs --budget <USD per month>", EXIT.configError);
486
489
  const { roxyon } = await requireSession();
487
490
  try {
488
491
  const t = await roxyon.tokens.create(name, {
489
492
  scopes,
490
- expiresInDays: opts.expires && opts.expires > 0 ? opts.expires : void 0
493
+ expiresInDays: opts.expires && opts.expires > 0 ? opts.expires : void 0,
494
+ ...ordering ? {
495
+ monthlyBudgetUSD: opts.budget,
496
+ allowedSkus: opts.skus ? opts.skus.split(",").map((x) => x.trim().toUpperCase()) : []
497
+ } : {}
491
498
  });
492
499
  ui.success(
493
500
  `Created "${t.name}" (${t.scopes.join(", ")})${t.expiresAt ? ` \xB7 expires ${t.expiresAt.slice(0, 10)}` : ""}`
@@ -585,7 +592,11 @@ env.command("rm <keys...>").description("Remove one or more variables").option("
585
592
  program.command("restart").description("Restart the application process (no rebuild)").option("--app <id>").action((opts) => run(() => restart(opts)));
586
593
  program.command("open").description("Open the project's URL in a browser").action(() => run(open));
587
594
  var token = program.command("token").description("Manage personal access tokens (for CI and the MCP server)");
588
- token.command("create <name>").description("Create a token \u2014 prints the secret once").option("--scopes <list>", "comma-separated: deploy,logs,read", "deploy,logs").option("--expires <days>", "expire after N days", (v) => Number.parseInt(v, 10)).action((name, opts) => run(() => tokenCreate(name, opts)));
595
+ token.command("create <name>").description("Create a token \u2014 prints the secret once").option("--scopes <list>", "comma-separated: deploy,logs,read,billing:order", "deploy,logs").option("--expires <days>", "expire after N days", (v) => Number.parseInt(v, 10)).option(
596
+ "--budget <usd>",
597
+ "billing:order: most it may order per month, USD",
598
+ (v) => Number.parseFloat(v)
599
+ ).option("--skus <list>", "billing:order: plan codes it may order, e.g. SCALE-S,LAUNCH-M").action((name, opts) => run(() => tokenCreate(name, opts)));
589
600
  token.command("list").description("List your tokens").action(() => run(tokenList));
590
601
  token.command("revoke <id>").description("Revoke a token").action((id) => run(() => tokenRevoke(id)));
591
602
  program.command("link [repoUrl]").description("Connect a git remote for push-to-deploy").option("--branch <branch>", "branch to deploy", "main").option("--app <id>").action((repoUrl, opts) => run(() => link(repoUrl, opts)));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/deploy.ts","../src/context.ts","../src/config.ts","../src/ui.ts","../src/commands/env.ts","../src/commands/init.ts","../src/commands/login.ts","../src/commands/logs.ts","../src/commands/misc.ts","../src/commands/token.ts","../src/commands/whoami.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { deploy } from './commands/deploy.js';\nimport { envPull, envRm, envSet } from './commands/env.js';\nimport { init } from './commands/init.js';\nimport { login, logout } from './commands/login.js';\nimport { logs } from './commands/logs.js';\nimport { link, open, restart } from './commands/misc.js';\nimport { tokenCreate, tokenList, tokenRevoke } from './commands/token.js';\nimport { whoami } from './commands/whoami.js';\nimport { CliError, EXIT, ui } from './ui.js';\n\nconst VERSION = '0.1.0';\n\nconst program = new Command();\n\nprogram\n .name('roxyon')\n .description('Deploy LumenJS apps and web projects to Roxyon infrastructure.')\n .version(VERSION, '-v, --version');\n\nprogram\n .command('login')\n .description('Sign in to Roxyon (email + password, with OTP if required)')\n .option('--email <email>')\n .option('--password <password>')\n .option('--otp <code>', 'one-time code, for non-interactive step-up')\n .option('--token <token>', 'use a session/personal token directly (CI)')\n .action((opts) => run(() => login(opts)));\n\nprogram\n .command('logout')\n .description('Remove stored credentials')\n .action(() => run(logout));\n\nprogram\n .command('whoami')\n .description('Show the signed-in user and subscriptions')\n .action(() => run(whoami));\n\nprogram\n .command('init')\n .description('Create roxyon.json for this project')\n .option('--host <host>', 'route host')\n .option('--folder <folder>', 'sub-path / source folder')\n .option('--runtime <runtime>', 'lumen | node | python | php')\n .option('-y, --yes', 'accept detected defaults, no prompts')\n .action((opts) => run(() => init(opts)));\n\nprogram\n .command('deploy')\n .description('Build (if configured) and deploy this project')\n .option('--no-build', 'skip the configured build command')\n .option('--no-follow', 'return once the build is queued (app runtimes)')\n .option('--lines <n>', 'log lines to stream while building', (v) => Number.parseInt(v, 10))\n .action((opts) => run(() => deploy(opts)));\n\nprogram\n .command('logs')\n .description('Show application logs')\n .option('-f, --follow', 'stream new lines')\n .option('--lines <n>', 'how many lines', (v) => Number.parseInt(v, 10))\n .option('--app <id>', 'application id (defaults to roxyon.json)')\n .action((opts) => run(() => logs(opts)));\n\nconst env = program.command('env').description('Manage application environment variables');\nenv\n .command('pull')\n .description('Print the current environment as KEY=value lines')\n .option('--app <id>')\n .action((opts) => run(() => envPull(opts)));\nenv\n .command('set <pairs...>')\n .description('Set one or more KEY=value pairs')\n .option('--app <id>')\n .action((pairs, opts) => run(() => envSet(pairs, opts)));\nenv\n .command('rm <keys...>')\n .description('Remove one or more variables')\n .option('--app <id>')\n .action((keys, opts) => run(() => envRm(keys, opts)));\n\nprogram\n .command('restart')\n .description('Restart the application process (no rebuild)')\n .option('--app <id>')\n .action((opts) => run(() => restart(opts)));\n\nprogram\n .command('open')\n .description(\"Open the project's URL in a browser\")\n .action(() => run(open));\n\nconst token = program\n .command('token')\n .description('Manage personal access tokens (for CI and the MCP server)');\ntoken\n .command('create <name>')\n .description('Create a token — prints the secret once')\n .option('--scopes <list>', 'comma-separated: deploy,logs,read', 'deploy,logs')\n .option('--expires <days>', 'expire after N days', (v) => Number.parseInt(v, 10))\n .action((name, opts) => run(() => tokenCreate(name, opts)));\ntoken\n .command('list')\n .description('List your tokens')\n .action(() => run(tokenList));\ntoken\n .command('revoke <id>')\n .description('Revoke a token')\n .action((id) => run(() => tokenRevoke(id)));\n\nprogram\n .command('link [repoUrl]')\n .description('Connect a git remote for push-to-deploy')\n .option('--branch <branch>', 'branch to deploy', 'main')\n .option('--app <id>')\n .action((repoUrl, opts) => run(() => link(repoUrl, opts)));\n\nprogram.parseAsync().catch((err) => {\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(EXIT.failure);\n});\n\nasync function run(fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (err) {\n if (err instanceof CliError) {\n ui.error(err.message);\n process.exit(err.exitCode);\n }\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(EXIT.failure);\n }\n}\n","import * as p from '@clack/prompts';\nimport { DeployError, deployProject } from '@roxyon/deploy-core';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface DeployOptions {\n follow?: boolean;\n build?: boolean;\n lines?: number;\n}\n\nconst CODE: Record<DeployError['code'], number> = {\n 'no-config': EXIT.configError,\n auth: EXIT.authRequired,\n 'bad-host': EXIT.configError,\n 'build-failed': EXIT.failure,\n 'no-build-output': EXIT.failure,\n 'upload-failed': EXIT.failure,\n 'create-failed': EXIT.failure,\n};\n\nexport async function deploy(opts: DeployOptions): Promise<void> {\n const { roxyon, credentials } = await requireSession();\n const spin = p.spinner();\n let spinning = false;\n\n const reporter = {\n step: (msg: string) => {\n if (spinning) spin.message(msg);\n else {\n spin.start(msg);\n spinning = true;\n }\n },\n log: (line: string) => ui.dim(` ${line}`),\n };\n\n try {\n const outcome = await deployProject({\n cwd: process.cwd(),\n roxyon,\n preferredSubscription: credentials?.subscription,\n build: opts.build,\n follow: opts.follow,\n reporter,\n });\n\n if (outcome.kind === 'static' && outcome.ok) {\n spin.stop('Deployed.');\n ui.success(`${outcome.url} is live (${outcome.files} files).`);\n return;\n }\n if (outcome.kind === 'app' && outcome.ok) {\n spin.stop(\n outcome.status === 'running'\n ? `Live — revision ${outcome.revision} running.`\n : `Build queued (revision ${outcome.revision}).`,\n );\n if (outcome.url) ui.success(outcome.url);\n return;\n }\n // app, not ok\n spin.stop('Deploy failed.');\n if ('error' in outcome && outcome.error) {\n ui.line();\n ui.error(outcome.error);\n }\n process.exitCode = EXIT.failure;\n } catch (err) {\n if (spinning) spin.stop('Failed.');\n if (err instanceof DeployError) fail(err.message, CODE[err.code]);\n throw err;\n }\n}\n","import { Roxyon } from '@roxyon/api-client';\nimport { type Credentials, endpointsFromEnv, loadCredentials, tokenFromEnv } from './config.js';\nimport { EXIT, fail } from './ui.js';\n\nexport interface Session {\n roxyon: Roxyon;\n /** Present when authenticated via a stored login (not a bare CI token). */\n credentials?: Credentials;\n}\n\n/** Build a client from a `ROXYON_TOKEN` env var or the stored login. Fails if neither. */\nexport async function requireSession(): Promise<Session> {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n const envToken = tokenFromEnv();\n if (envToken) {\n return {\n roxyon: new Roxyon({ sessionToken: envToken, baseUrl: apiUrl, consoleUrl: consoleUrl }),\n };\n }\n\n const creds = await loadCredentials();\n if (!creds?.sessionToken) {\n fail('Not signed in. Run `roxyon login` (or set ROXYON_TOKEN for CI).', EXIT.authRequired);\n }\n return {\n roxyon: new Roxyon({ sessionToken: creds.sessionToken, baseUrl: apiUrl, consoleUrl }),\n credentials: creds,\n };\n}\n\n/** A client with no user auth — for the login flow itself. */\nexport function anonymousRoxyon(): Roxyon {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n return new Roxyon({ baseUrl: apiUrl, consoleUrl });\n}\n","/**\n * All config lives in `@roxyon/deploy-core` so the CLI and the MCP server share\n * one implementation. This module just re-exports it.\n */\nexport {\n buildProjectConfig,\n clearCredentials,\n type Credentials,\n credentialsPath,\n type Endpoints,\n endpointsFromEnv,\n loadCredentials,\n loadProjectConfig,\n type ProjectConfig,\n projectConfigPath,\n saveCredentials,\n saveProjectConfig,\n tokenFromEnv,\n} from '@roxyon/deploy-core';\n","import pc from 'picocolors';\n\nexport const ui = {\n info: (msg: string) => process.stdout.write(`${pc.cyan('›')} ${msg}\\n`),\n success: (msg: string) => process.stdout.write(`${pc.green('✓')} ${msg}\\n`),\n warn: (msg: string) => process.stderr.write(`${pc.yellow('!')} ${msg}\\n`),\n error: (msg: string) => process.stderr.write(`${pc.red('✗')} ${msg}\\n`),\n line: (msg = '') => process.stdout.write(`${msg}\\n`),\n dim: (msg: string) => process.stdout.write(`${pc.dim(msg)}\\n`),\n kv: (key: string, value: string) =>\n process.stdout.write(` ${pc.dim(key.padEnd(14))} ${value}\\n`),\n};\n\n/** Exit codes — kept stable for scripting / CI. */\nexport const EXIT = {\n ok: 0,\n failure: 1,\n authRequired: 2,\n configError: 3,\n} as const;\n\nexport class CliError extends Error {\n readonly exitCode: number;\n constructor(message: string, exitCode: number = EXIT.failure) {\n super(message);\n this.name = 'CliError';\n this.exitCode = exitCode;\n }\n}\n\nexport function fail(message: string, exitCode: number = EXIT.failure): never {\n throw new CliError(message, exitCode);\n}\n","import { RoxyonApiError, formatEnv } from '@roxyon/api-client';\nimport { loadProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nasync function resolveApp(explicit?: string): Promise<string> {\n const appId = explicit ?? (await loadProjectConfig())?.application;\n if (!appId)\n fail('No application. Pass --app <id> or deploy this project first.', EXIT.configError);\n return appId;\n}\n\nexport async function envPull(opts: { app?: string }): Promise<void> {\n const appId = await resolveApp(opts.app);\n const { roxyon } = await requireSession();\n try {\n const env = await roxyon.applications.getEnv(appId);\n ui.line(formatEnv(env) || '# (no environment variables set)');\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function envSet(pairs: string[], opts: { app?: string }): Promise<void> {\n if (pairs.length === 0)\n fail('Nothing to set. Usage: roxyon env set KEY=value [KEY2=value2]', EXIT.configError);\n const appId = await resolveApp(opts.app);\n\n const set: Record<string, string> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf('=');\n if (eq < 1) fail(`\"${pair}\" is not KEY=value.`, EXIT.configError);\n const key = pair.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) fail(`Invalid env key \"${key}\".`, EXIT.configError);\n if (key === 'PORT' || key === 'HOST') {\n ui.warn(`${key} is set by the platform — ignoring.`);\n continue;\n }\n set[key] = pair.slice(eq + 1);\n }\n\n const { roxyon } = await requireSession();\n try {\n const r = await roxyon.applications.setEnv(appId, { set });\n ui.success(`Updated ${r.changed.join(', ') || 'nothing'}. Run \\`roxyon deploy\\` to apply.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function envRm(keys: string[], opts: { app?: string }): Promise<void> {\n if (keys.length === 0)\n fail('Nothing to remove. Usage: roxyon env rm KEY [KEY2]', EXIT.configError);\n const appId = await resolveApp(opts.app);\n const { roxyon } = await requireSession();\n try {\n const r = await roxyon.applications.setEnv(appId, { remove: keys });\n ui.success(`Removed ${r.changed.join(', ') || 'nothing'}. Run \\`roxyon deploy\\` to apply.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { basename } from 'node:path';\nimport * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport type { RuntimeName } from '@roxyon/api-client';\nimport {\n buildProjectConfig,\n detectRuntime,\n loadProjectConfig,\n saveProjectConfig,\n} from '@roxyon/deploy-core';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface InitOptions {\n host?: string;\n folder?: string;\n runtime?: RuntimeName;\n yes?: boolean;\n}\n\nexport async function init(opts: InitOptions): Promise<void> {\n const cwd = process.cwd();\n const existing = await loadProjectConfig(cwd);\n if (existing && !opts.yes) {\n const overwrite = await ask(() =>\n p.confirm({ message: 'roxyon.json already exists — overwrite it?', initialValue: false }),\n );\n if (!overwrite) return;\n }\n\n const { roxyon, credentials } = await requireSession();\n const user = await roxyon.auth.me();\n const sub = await roxyon.subscriptions.resolve(user.objectId, credentials?.subscription);\n const domains = await roxyon.domains.list(sub.objectId);\n if (domains.length === 0) {\n fail(\n 'This subscription has no hosts yet. Add a domain in the console, then run `roxyon init` again.',\n EXIT.configError,\n );\n }\n\n const detected = await detectRuntime(cwd);\n ui.info(`Detected runtime: ${detected.runtime} — ${detected.reason}`);\n\n const runtime: RuntimeName = opts.runtime\n ? opts.runtime\n : opts.yes\n ? detected.runtime\n : await ask<RuntimeName>(() =>\n p.select({\n message: 'Runtime',\n initialValue: detected.runtime,\n options: [\n { value: 'lumen', label: 'LumenJS (static SPA, no server)' },\n { value: 'node', label: 'Node.js app' },\n { value: 'python', label: 'Python app' },\n { value: 'php', label: 'PHP app' },\n ],\n }),\n );\n\n const host: string =\n opts.host ??\n (opts.yes\n ? (domains[0]?.Name ?? fail('No host available.', EXIT.configError))\n : await ask<string>(() =>\n p.select({\n message: 'Host',\n options: domains.map((d) => ({ value: d.Name, label: d.Name })),\n }),\n ));\n\n const defaultFolder = basename(cwd).replace(/[^a-z0-9._-]/gi, '-');\n const folder =\n opts.folder ??\n (opts.yes\n ? runtime === 'lumen'\n ? ''\n : defaultFolder\n : await ask<string>(() =>\n p.text({\n message:\n runtime === 'lumen'\n ? 'Sub-path under the host root (blank = site root)'\n : 'Folder under the host (source location)',\n placeholder: runtime === 'lumen' ? '(root)' : defaultFolder,\n defaultValue: runtime === 'lumen' ? '' : defaultFolder,\n }),\n ));\n\n const config = buildProjectConfig({\n cwd,\n runtime,\n host,\n folder,\n name: basename(cwd),\n start: detected.start,\n });\n\n const path = await saveProjectConfig(config, cwd);\n ui.success(`Wrote ${path}`);\n ui.line();\n ui.dim(JSON.stringify(config, null, 2));\n ui.line();\n ui.info('Next: `roxyon deploy`');\n}\n\nasync function ask<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const v = await fn();\n if (isCancel(v)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return v as T;\n}\n","import * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport { RoxyonApiError } from '@roxyon/api-client';\nimport { type Credentials, clearCredentials, loadCredentials, saveCredentials } from '../config.js';\nimport { anonymousRoxyon } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface LoginOptions {\n email?: string;\n password?: string;\n token?: string;\n otp?: string;\n}\n\nexport async function login(opts: LoginOptions): Promise<void> {\n const roxyon = anonymousRoxyon();\n\n // Non-interactive: a token was handed in directly.\n if (opts.token) {\n roxyon.client.setSessionToken(opts.token);\n const user = await roxyon.auth.me().catch((e) => {\n fail(`That token did not authenticate: ${(e as Error).message}`, EXIT.authRequired);\n });\n await persist({ sessionToken: opts.token, userId: user.objectId, email: user.Email });\n ui.success(`Signed in as ${user.Email ?? user.objectId} (via --token).`);\n return;\n }\n\n const interactive = process.stdin.isTTY && !opts.password;\n\n const email =\n opts.email ??\n (interactive\n ? await prompt(() =>\n p.text({\n message: 'Email',\n validate: (v) => (v.includes('@') ? undefined : 'Enter an email'),\n }),\n )\n : fail(\n 'Provide --email (and --password), or run in an interactive terminal.',\n EXIT.configError,\n ));\n\n const password =\n opts.password ??\n (interactive\n ? await prompt(() => p.password({ message: 'Password' }))\n : fail('Provide --password.', EXIT.configError));\n\n const spin = p.spinner();\n spin.start('Signing in');\n try {\n let result = await roxyon.auth.login(email, password, { via: 'cli' });\n\n if (result.stepUpRequired) {\n spin.stop('A one-time code was sent to you.');\n const code =\n opts.otp ??\n (interactive\n ? await prompt(() => p.text({ message: 'One-time code' }))\n : fail('This account requires OTP — pass --otp <code>.', EXIT.authRequired));\n spin.start('Verifying code');\n result = await roxyon.auth.verifyOtp(result.challengeId ?? '', code);\n }\n\n roxyon.client.setSessionToken(result.sessionToken);\n const user = await roxyon.auth.me();\n await persist({\n sessionToken: result.sessionToken,\n refreshToken: result.refreshToken,\n userId: user.objectId,\n email: user.Email,\n });\n spin.stop(`Signed in as ${user.Email ?? user.objectId}.`);\n ui.dim('Token stored in ~/.roxyon/config.json (permissions 0600).');\n } catch (err) {\n spin.stop('Sign-in failed.');\n if (err instanceof RoxyonApiError) fail(err.message, EXIT.authRequired);\n throw err;\n }\n}\n\nexport async function logout(): Promise<void> {\n const creds = await loadCredentials();\n await clearCredentials();\n ui.success(creds ? `Signed out ${creds.email ?? creds.userId}.` : 'Nothing to sign out.');\n}\n\nasync function persist(partial: Omit<Credentials, 'savedAt'>): Promise<void> {\n await saveCredentials({ ...partial, savedAt: new Date().toISOString() });\n}\n\nasync function prompt<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const value = await fn();\n if (isCancel(value)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return value as T;\n}\n","import { RoxyonApiError } from '@roxyon/api-client';\nimport { loadProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface LogsOptions {\n follow?: boolean;\n lines?: number;\n app?: string;\n}\n\nexport async function logs(opts: LogsOptions): Promise<void> {\n const appId = opts.app ?? (await loadProjectConfig())?.application;\n if (!appId) {\n fail(\n 'No application. Pass --app <id>, or run from a project whose roxyon.json has one.',\n EXIT.configError,\n );\n }\n\n const { roxyon } = await requireSession();\n const lines = opts.lines ?? 100;\n\n if (!opts.follow) {\n for (const l of await fetchLogs(\n roxyon.applications.logs.bind(roxyon.applications),\n appId,\n lines,\n )) {\n ui.line(l);\n }\n return;\n }\n\n ui.dim(`Following ${appId} — Ctrl-C to stop.`);\n let seen = new Set<string>();\n const tick = async () => {\n try {\n for (const l of await roxyon.applications.logs(appId, lines)) {\n if (l && !seen.has(l)) {\n seen.add(l);\n ui.line(l);\n }\n }\n if (seen.size > 4000) seen = new Set([...seen].slice(-2000));\n } catch (err) {\n ui.warn((err as Error).message);\n }\n };\n await tick();\n const timer = setInterval(tick, 7000);\n process.on('SIGINT', () => {\n clearInterval(timer);\n process.exit(EXIT.ok);\n });\n}\n\nasync function fetchLogs(\n fn: (id: string, n: number) => Promise<string[]>,\n appId: string,\n lines: number,\n): Promise<string[]> {\n try {\n return await fn(appId, lines);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { spawn } from 'node:child_process';\nimport { platform } from 'node:os';\nimport * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport { RoxyonApiError } from '@roxyon/api-client';\nimport { loadProjectConfig, saveProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport async function restart(opts: { app?: string }): Promise<void> {\n const appId = opts.app ?? (await loadProjectConfig())?.application;\n if (!appId)\n fail('No application. Pass --app <id> or deploy this project first.', EXIT.configError);\n const { roxyon } = await requireSession();\n try {\n await roxyon.applications.restart(appId);\n ui.success('Restart queued.');\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function open(): Promise<void> {\n const config = await loadProjectConfig();\n if (!config) fail('No roxyon.json here.', EXIT.configError);\n const url = `https://${config.host}${config.folder ? `/${config.folder}` : ''}`;\n const cmd = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';\n spawn(cmd, [url], { stdio: 'ignore', detached: true, shell: platform() === 'win32' }).unref();\n ui.info(`Opening ${url}`);\n}\n\nexport async function link(\n repoUrl: string | undefined,\n opts: { branch?: string; app?: string },\n): Promise<void> {\n const config = await loadProjectConfig();\n const appId = opts.app ?? config?.application;\n if (!appId)\n fail(\n 'Deploy the project once first so an application exists, then `roxyon link`.',\n EXIT.configError,\n );\n\n const url =\n repoUrl ??\n (process.stdin.isTTY\n ? await ask(() =>\n p.text({ message: 'Git remote (SSH URL)', placeholder: 'git@github.com:you/app.git' }),\n )\n : fail('Pass the git remote URL: roxyon link <url>', EXIT.configError));\n const branch = opts.branch ?? 'main';\n\n const { roxyon } = await requireSession();\n try {\n const res = await roxyon.applications.repoConnect(appId, url, branch);\n ui.success(`Connected ${url} (${branch}).`);\n ui.line();\n if (res.deployKey) {\n ui.info('Add this deploy key to the repo (read-only is enough):');\n ui.line(res.deployKey);\n ui.line();\n }\n if (res.webhookUrl) {\n ui.info('Add a push webhook:');\n ui.kv('URL', res.webhookUrl);\n if (res.secret) ui.kv('Secret', res.secret);\n ui.line();\n }\n if (res.hint) ui.dim(res.hint);\n if (config) {\n // Record the remote so `roxyon deploy` can note that pushes auto-deploy.\n await saveProjectConfig({ ...config }, process.cwd());\n }\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nasync function ask<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const v = await fn();\n if (isCancel(v)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return v as T;\n}\n","import { RoxyonApiError, type TokenScope } from '@roxyon/api-client';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nconst SCOPES: TokenScope[] = ['deploy', 'logs', 'read'];\n\nexport async function tokenCreate(\n name: string | undefined,\n opts: { scopes?: string; expires?: number },\n): Promise<void> {\n if (!name) fail('A name is required: roxyon token create <name>', EXIT.configError);\n\n const scopes = (opts.scopes ? opts.scopes.split(',') : ['deploy', 'logs'])\n .map((s) => s.trim().toLowerCase())\n .filter((s): s is TokenScope => (SCOPES as string[]).includes(s));\n if (scopes.length === 0)\n fail(`--scopes must be a subset of: ${SCOPES.join(', ')}`, EXIT.configError);\n\n const { roxyon } = await requireSession();\n try {\n const t = await roxyon.tokens.create(name, {\n scopes,\n expiresInDays: opts.expires && opts.expires > 0 ? opts.expires : undefined,\n });\n ui.success(\n `Created \"${t.name}\" (${t.scopes.join(', ')})${t.expiresAt ? ` · expires ${t.expiresAt.slice(0, 10)}` : ''}`,\n );\n ui.line();\n ui.line(t.token);\n ui.line();\n ui.dim(\n 'Copy it now — it will not be shown again. Use it as ROXYON_TOKEN in CI or the MCP server.',\n );\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function tokenList(): Promise<void> {\n const { roxyon } = await requireSession();\n try {\n const tokens = await roxyon.tokens.list();\n if (tokens.length === 0) {\n ui.info('No personal access tokens.');\n return;\n }\n ui.line();\n for (const t of tokens) {\n ui.kv(\n t.name,\n `${t.prefix}… · ${t.scopes.join(',')}` +\n `${t.expiresAt ? ` · expires ${t.expiresAt.slice(0, 10)}` : ''}` +\n `${t.lastUsedAt ? ` · used ${t.lastUsedAt.slice(0, 10)}` : ' · never used'}`,\n );\n ui.dim(` id ${t.id}`);\n }\n ui.line();\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function tokenRevoke(id: string | undefined): Promise<void> {\n if (!id) fail('A token id is required: roxyon token revoke <id>', EXIT.configError);\n const { roxyon } = await requireSession();\n try {\n await roxyon.tokens.revoke(id);\n ui.success(`Revoked ${id}.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { isAuthError } from '@roxyon/api-client';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport async function whoami(): Promise<void> {\n const { roxyon, credentials } = await requireSession();\n try {\n // One call — works with a session token or a PAT.\n const ctx = await roxyon.account.context();\n ui.line();\n ui.kv('User', ctx.user.email || ctx.user.id);\n ui.kv('User ID', ctx.user.id);\n if (credentials?.sessionToken?.startsWith('roxp_')) {\n ui.kv('Auth', `personal access token (${ctx.scopes.join(', ') || 'no scopes'})`);\n }\n if (ctx.subscriptions.length === 0) {\n ui.kv('Subscription', '(none — add a plan in the console)');\n } else {\n const active =\n (credentials?.subscription &&\n ctx.subscriptions.find(\n (s) => s.id === credentials.subscription || s.name === credentials.subscription,\n )) ||\n ctx.subscriptions.find((s) => s.status === 'active') ||\n ctx.subscriptions[0];\n for (const s of ctx.subscriptions) {\n const mark = s.id === active?.id ? '→ ' : ' ';\n ui.kv(`${mark}${s.name || s.id}`, s.status || '?');\n }\n }\n ui.kv('Hosts', ctx.domains.map((d) => d.name).join(', ') || '(none)');\n ui.line();\n } catch (err) {\n if (isAuthError(err)) fail('Session expired. Run `roxyon login` again.', EXIT.authRequired);\n throw err;\n }\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACAxB,YAAY,OAAO;AACnB,SAAS,aAAa,qBAAqB;;;ACD3C,SAAS,cAAc;;;ACIvB;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;AClBP,OAAO,QAAQ;AAER,IAAM,KAAK;AAAA,EAChB,MAAM,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG,KAAK,QAAG,CAAC,IAAI,GAAG;AAAA,CAAI;AAAA,EACtE,SAAS,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG,MAAM,QAAG,CAAC,IAAI,GAAG;AAAA,CAAI;AAAA,EAC1E,MAAM,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,IAAI,GAAG;AAAA,CAAI;AAAA,EACxE,OAAO,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG,IAAI,QAAG,CAAC,IAAI,GAAG;AAAA,CAAI;AAAA,EACtE,MAAM,CAAC,MAAM,OAAO,QAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAAA,EACnD,KAAK,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;AAAA,CAAI;AAAA,EAC7D,IAAI,CAAC,KAAa,UAChB,QAAQ,OAAO,MAAM,KAAK,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK;AAAA,CAAI;AACjE;AAGO,IAAM,OAAO;AAAA,EAClB,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,cAAc;AAAA,EACd,aAAa;AACf;AAEO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACT,YAAY,SAAiB,WAAmB,KAAK,SAAS;AAC5D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,WAAW;AAAA,EAClB;AACF;AAEO,SAAS,KAAK,SAAiB,WAAmB,KAAK,SAAgB;AAC5E,QAAM,IAAI,SAAS,SAAS,QAAQ;AACtC;;;AFrBA,eAAsB,iBAAmC;AACvD,QAAM,EAAE,QAAQ,WAAW,IAAI,iBAAiB;AAChD,QAAM,WAAW,aAAa;AAC9B,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,QAAQ,IAAI,OAAO,EAAE,cAAc,UAAU,SAAS,QAAQ,WAAuB,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,gBAAgB;AACpC,MAAI,CAAC,OAAO,cAAc;AACxB,SAAK,mEAAmE,KAAK,YAAY;AAAA,EAC3F;AACA,SAAO;AAAA,IACL,QAAQ,IAAI,OAAO,EAAE,cAAc,MAAM,cAAc,SAAS,QAAQ,WAAW,CAAC;AAAA,IACpF,aAAa;AAAA,EACf;AACF;AAGO,SAAS,kBAA0B;AACxC,QAAM,EAAE,QAAQ,WAAW,IAAI,iBAAiB;AAChD,SAAO,IAAI,OAAO,EAAE,SAAS,QAAQ,WAAW,CAAC;AACnD;;;ADvBA,IAAM,OAA4C;AAAA,EAChD,aAAa,KAAK;AAAA,EAClB,MAAM,KAAK;AAAA,EACX,YAAY,KAAK;AAAA,EACjB,gBAAgB,KAAK;AAAA,EACrB,mBAAmB,KAAK;AAAA,EACxB,iBAAiB,KAAK;AAAA,EACtB,iBAAiB,KAAK;AACxB;AAEA,eAAsB,OAAO,MAAoC;AAC/D,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,eAAe;AACrD,QAAM,OAAS,UAAQ;AACvB,MAAI,WAAW;AAEf,QAAM,WAAW;AAAA,IACf,MAAM,CAAC,QAAgB;AACrB,UAAI,SAAU,MAAK,QAAQ,GAAG;AAAA,WACzB;AACH,aAAK,MAAM,GAAG;AACd,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,KAAK,CAAC,SAAiB,GAAG,IAAI,KAAK,IAAI,EAAE;AAAA,EAC3C;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,cAAc;AAAA,MAClC,KAAK,QAAQ,IAAI;AAAA,MACjB;AAAA,MACA,uBAAuB,aAAa;AAAA,MACpC,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb;AAAA,IACF,CAAC;AAED,QAAI,QAAQ,SAAS,YAAY,QAAQ,IAAI;AAC3C,WAAK,KAAK,WAAW;AACrB,SAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,QAAQ,KAAK,UAAU;AAC7D;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,SAAS,QAAQ,IAAI;AACxC,WAAK;AAAA,QACH,QAAQ,WAAW,YACf,wBAAmB,QAAQ,QAAQ,cACnC,0BAA0B,QAAQ,QAAQ;AAAA,MAChD;AACA,UAAI,QAAQ,IAAK,IAAG,QAAQ,QAAQ,GAAG;AACvC;AAAA,IACF;AAEA,SAAK,KAAK,gBAAgB;AAC1B,QAAI,WAAW,WAAW,QAAQ,OAAO;AACvC,SAAG,KAAK;AACR,SAAG,MAAM,QAAQ,KAAK;AAAA,IACxB;AACA,YAAQ,WAAW,KAAK;AAAA,EAC1B,SAAS,KAAK;AACZ,QAAI,SAAU,MAAK,KAAK,SAAS;AACjC,QAAI,eAAe,YAAa,MAAK,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC;AAChE,UAAM;AAAA,EACR;AACF;;;AIzEA,SAAS,gBAAgB,iBAAiB;AAK1C,eAAe,WAAW,UAAoC;AAC5D,QAAM,QAAQ,aAAa,MAAM,kBAAkB,IAAI;AACvD,MAAI,CAAC;AACH,SAAK,iEAAiE,KAAK,WAAW;AACxF,SAAO;AACT;AAEA,eAAsB,QAAQ,MAAuC;AACnE,QAAM,QAAQ,MAAM,WAAW,KAAK,GAAG;AACvC,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAMA,OAAM,MAAM,OAAO,aAAa,OAAO,KAAK;AAClD,OAAG,KAAK,UAAUA,IAAG,KAAK,kCAAkC;AAAA,EAC9D,SAAS,KAAK;AACZ,QAAI,eAAe,eAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,OAAO,OAAiB,MAAuC;AACnF,MAAI,MAAM,WAAW;AACnB,SAAK,iEAAiE,KAAK,WAAW;AACxF,QAAM,QAAQ,MAAM,WAAW,KAAK,GAAG;AAEvC,QAAM,MAA8B,CAAC;AACrC,aAAW,QAAQ,OAAO;AACxB,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,QAAI,KAAK,EAAG,MAAK,IAAI,IAAI,uBAAuB,KAAK,WAAW;AAChE,UAAM,MAAM,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AACnC,QAAI,CAAC,2BAA2B,KAAK,GAAG,EAAG,MAAK,oBAAoB,GAAG,MAAM,KAAK,WAAW;AAC7F,QAAI,QAAQ,UAAU,QAAQ,QAAQ;AACpC,SAAG,KAAK,GAAG,GAAG,0CAAqC;AACnD;AAAA,IACF;AACA,QAAI,GAAG,IAAI,KAAK,MAAM,KAAK,CAAC;AAAA,EAC9B;AAEA,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,IAAI,MAAM,OAAO,aAAa,OAAO,OAAO,EAAE,IAAI,CAAC;AACzD,OAAG,QAAQ,WAAW,EAAE,QAAQ,KAAK,IAAI,KAAK,SAAS,mCAAmC;AAAA,EAC5F,SAAS,KAAK;AACZ,QAAI,eAAe,eAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,MAAM,MAAgB,MAAuC;AACjF,MAAI,KAAK,WAAW;AAClB,SAAK,sDAAsD,KAAK,WAAW;AAC7E,QAAM,QAAQ,MAAM,WAAW,KAAK,GAAG;AACvC,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,IAAI,MAAM,OAAO,aAAa,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAClE,OAAG,QAAQ,WAAW,EAAE,QAAQ,KAAK,IAAI,KAAK,SAAS,mCAAmC;AAAA,EAC5F,SAAS,KAAK;AACZ,QAAI,eAAe,eAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;;;AChEA,SAAS,gBAAgB;AACzB,YAAYC,QAAO;AACnB,SAAS,gBAAgB;AAEzB;AAAA,EACE,sBAAAC;AAAA,EACA;AAAA,EACA,qBAAAC;AAAA,EACA,qBAAAC;AAAA,OACK;AAWP,eAAsB,KAAK,MAAkC;AAC3D,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,WAAW,MAAMC,mBAAkB,GAAG;AAC5C,MAAI,YAAY,CAAC,KAAK,KAAK;AACzB,UAAM,YAAY,MAAM;AAAA,MAAI,MACxB,WAAQ,EAAE,SAAS,mDAA8C,cAAc,MAAM,CAAC;AAAA,IAC1F;AACA,QAAI,CAAC,UAAW;AAAA,EAClB;AAEA,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,eAAe;AACrD,QAAM,OAAO,MAAM,OAAO,KAAK,GAAG;AAClC,QAAM,MAAM,MAAM,OAAO,cAAc,QAAQ,KAAK,UAAU,aAAa,YAAY;AACvF,QAAM,UAAU,MAAM,OAAO,QAAQ,KAAK,IAAI,QAAQ;AACtD,MAAI,QAAQ,WAAW,GAAG;AACxB;AAAA,MACE;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,cAAc,GAAG;AACxC,KAAG,KAAK,qBAAqB,SAAS,OAAO,WAAM,SAAS,MAAM,EAAE;AAEpE,QAAM,UAAuB,KAAK,UAC9B,KAAK,UACL,KAAK,MACH,SAAS,UACT,MAAM;AAAA,IAAiB,MACnB,UAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc,SAAS;AAAA,MACvB,SAAS;AAAA,QACP,EAAE,OAAO,SAAS,OAAO,kCAAkC;AAAA,QAC3D,EAAE,OAAO,QAAQ,OAAO,cAAc;AAAA,QACtC,EAAE,OAAO,UAAU,OAAO,aAAa;AAAA,QACvC,EAAE,OAAO,OAAO,OAAO,UAAU;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAEN,QAAM,OACJ,KAAK,SACJ,KAAK,MACD,QAAQ,CAAC,GAAG,QAAQ,KAAK,sBAAsB,KAAK,WAAW,IAChE,MAAM;AAAA,IAAY,MACd,UAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS,QAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,EAAE,KAAK,EAAE;AAAA,IAChE,CAAC;AAAA,EACH;AAEN,QAAM,gBAAgB,SAAS,GAAG,EAAE,QAAQ,kBAAkB,GAAG;AACjE,QAAM,SACJ,KAAK,WACJ,KAAK,MACF,YAAY,UACV,KACA,gBACF,MAAM;AAAA,IAAY,MACd,QAAK;AAAA,MACL,SACE,YAAY,UACR,qDACA;AAAA,MACN,aAAa,YAAY,UAAU,WAAW;AAAA,MAC9C,cAAc,YAAY,UAAU,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AAEN,QAAM,SAASC,oBAAmB;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,SAAS,GAAG;AAAA,IAClB,OAAO,SAAS;AAAA,EAClB,CAAC;AAED,QAAM,OAAO,MAAMC,mBAAkB,QAAQ,GAAG;AAChD,KAAG,QAAQ,SAAS,IAAI,EAAE;AAC1B,KAAG,KAAK;AACR,KAAG,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACtC,KAAG,KAAK;AACR,KAAG,KAAK,uBAAuB;AACjC;AAEA,eAAe,IAAO,IAA2C;AAC/D,QAAM,IAAI,MAAM,GAAG;AACnB,MAAI,SAAS,CAAC,GAAG;AACf,IAAE,UAAO,YAAY;AACrB,YAAQ,KAAK,KAAK,EAAE;AAAA,EACtB;AACA,SAAO;AACT;;;AClHA,YAAYC,QAAO;AACnB,SAAS,YAAAC,iBAAgB;AACzB,SAAS,kBAAAC,uBAAsB;AAY/B,eAAsB,MAAM,MAAmC;AAC7D,QAAM,SAAS,gBAAgB;AAG/B,MAAI,KAAK,OAAO;AACd,WAAO,OAAO,gBAAgB,KAAK,KAAK;AACxC,UAAM,OAAO,MAAM,OAAO,KAAK,GAAG,EAAE,MAAM,CAAC,MAAM;AAC/C,WAAK,oCAAqC,EAAY,OAAO,IAAI,KAAK,YAAY;AAAA,IACpF,CAAC;AACD,UAAM,QAAQ,EAAE,cAAc,KAAK,OAAO,QAAQ,KAAK,UAAU,OAAO,KAAK,MAAM,CAAC;AACpF,OAAG,QAAQ,gBAAgB,KAAK,SAAS,KAAK,QAAQ,iBAAiB;AACvE;AAAA,EACF;AAEA,QAAM,cAAc,QAAQ,MAAM,SAAS,CAAC,KAAK;AAEjD,QAAM,QACJ,KAAK,UACJ,cACG,MAAM;AAAA,IAAO,MACT,QAAK;AAAA,MACL,SAAS;AAAA,MACT,UAAU,CAAC,MAAO,EAAE,SAAS,GAAG,IAAI,SAAY;AAAA,IAClD,CAAC;AAAA,EACH,IACA;AAAA,IACE;AAAA,IACA,KAAK;AAAA,EACP;AAEN,QAAMC,YACJ,KAAK,aACJ,cACG,MAAM,OAAO,MAAQ,YAAS,EAAE,SAAS,WAAW,CAAC,CAAC,IACtD,KAAK,uBAAuB,KAAK,WAAW;AAElD,QAAM,OAAS,WAAQ;AACvB,OAAK,MAAM,YAAY;AACvB,MAAI;AACF,QAAI,SAAS,MAAM,OAAO,KAAK,MAAM,OAAOA,WAAU,EAAE,KAAK,MAAM,CAAC;AAEpE,QAAI,OAAO,gBAAgB;AACzB,WAAK,KAAK,kCAAkC;AAC5C,YAAM,OACJ,KAAK,QACJ,cACG,MAAM,OAAO,MAAQ,QAAK,EAAE,SAAS,gBAAgB,CAAC,CAAC,IACvD,KAAK,uDAAkD,KAAK,YAAY;AAC9E,WAAK,MAAM,gBAAgB;AAC3B,eAAS,MAAM,OAAO,KAAK,UAAU,OAAO,eAAe,IAAI,IAAI;AAAA,IACrE;AAEA,WAAO,OAAO,gBAAgB,OAAO,YAAY;AACjD,UAAM,OAAO,MAAM,OAAO,KAAK,GAAG;AAClC,UAAM,QAAQ;AAAA,MACZ,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,MACrB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,KAAK,gBAAgB,KAAK,SAAS,KAAK,QAAQ,GAAG;AACxD,OAAG,IAAI,2DAA2D;AAAA,EACpE,SAAS,KAAK;AACZ,SAAK,KAAK,iBAAiB;AAC3B,QAAI,eAAeC,gBAAgB,MAAK,IAAI,SAAS,KAAK,YAAY;AACtE,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,SAAwB;AAC5C,QAAM,QAAQ,MAAM,gBAAgB;AACpC,QAAM,iBAAiB;AACvB,KAAG,QAAQ,QAAQ,cAAc,MAAM,SAAS,MAAM,MAAM,MAAM,sBAAsB;AAC1F;AAEA,eAAe,QAAQ,SAAsD;AAC3E,QAAM,gBAAgB,EAAE,GAAG,SAAS,UAAS,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AACzE;AAEA,eAAe,OAAU,IAA2C;AAClE,QAAM,QAAQ,MAAM,GAAG;AACvB,MAAIC,UAAS,KAAK,GAAG;AACnB,IAAE,UAAO,YAAY;AACrB,YAAQ,KAAK,KAAK,EAAE;AAAA,EACtB;AACA,SAAO;AACT;;;ACpGA,SAAS,kBAAAC,uBAAsB;AAW/B,eAAsB,KAAK,MAAkC;AAC3D,QAAM,QAAQ,KAAK,QAAQ,MAAM,kBAAkB,IAAI;AACvD,MAAI,CAAC,OAAO;AACV;AAAA,MACE;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,QAAM,QAAQ,KAAK,SAAS;AAE5B,MAAI,CAAC,KAAK,QAAQ;AAChB,eAAW,KAAK,MAAM;AAAA,MACpB,OAAO,aAAa,KAAK,KAAK,OAAO,YAAY;AAAA,MACjD;AAAA,MACA;AAAA,IACF,GAAG;AACD,SAAG,KAAK,CAAC;AAAA,IACX;AACA;AAAA,EACF;AAEA,KAAG,IAAI,aAAa,KAAK,yBAAoB;AAC7C,MAAI,OAAO,oBAAI,IAAY;AAC3B,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,iBAAW,KAAK,MAAM,OAAO,aAAa,KAAK,OAAO,KAAK,GAAG;AAC5D,YAAI,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG;AACrB,eAAK,IAAI,CAAC;AACV,aAAG,KAAK,CAAC;AAAA,QACX;AAAA,MACF;AACA,UAAI,KAAK,OAAO,IAAM,QAAO,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,IAAK,CAAC;AAAA,IAC7D,SAAS,KAAK;AACZ,SAAG,KAAM,IAAc,OAAO;AAAA,IAChC;AAAA,EACF;AACA,QAAM,KAAK;AACX,QAAM,QAAQ,YAAY,MAAM,GAAI;AACpC,UAAQ,GAAG,UAAU,MAAM;AACzB,kBAAc,KAAK;AACnB,YAAQ,KAAK,KAAK,EAAE;AAAA,EACtB,CAAC;AACH;AAEA,eAAe,UACb,IACA,OACA,OACmB;AACnB,MAAI;AACF,WAAO,MAAM,GAAG,OAAO,KAAK;AAAA,EAC9B,SAAS,KAAK;AACZ,QAAI,eAAeC,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;;;ACpEA,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,YAAYC,QAAO;AACnB,SAAS,YAAAC,iBAAgB;AACzB,SAAS,kBAAAC,uBAAsB;AAK/B,eAAsB,QAAQ,MAAuC;AACnE,QAAM,QAAQ,KAAK,QAAQ,MAAM,kBAAkB,IAAI;AACvD,MAAI,CAAC;AACH,SAAK,iEAAiE,KAAK,WAAW;AACxF,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,OAAO,aAAa,QAAQ,KAAK;AACvC,OAAG,QAAQ,iBAAiB;AAAA,EAC9B,SAAS,KAAK;AACZ,QAAI,eAAeC,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,OAAsB;AAC1C,QAAM,SAAS,MAAM,kBAAkB;AACvC,MAAI,CAAC,OAAQ,MAAK,wBAAwB,KAAK,WAAW;AAC1D,QAAM,MAAM,WAAW,OAAO,IAAI,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,KAAK,EAAE;AAC7E,QAAM,MAAM,SAAS,MAAM,WAAW,SAAS,SAAS,MAAM,UAAU,UAAU;AAClF,QAAM,KAAK,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,UAAU,MAAM,OAAO,SAAS,MAAM,QAAQ,CAAC,EAAE,MAAM;AAC5F,KAAG,KAAK,WAAW,GAAG,EAAE;AAC1B;AAEA,eAAsB,KACpB,SACA,MACe;AACf,QAAM,SAAS,MAAM,kBAAkB;AACvC,QAAM,QAAQ,KAAK,OAAO,QAAQ;AAClC,MAAI,CAAC;AACH;AAAA,MACE;AAAA,MACA,KAAK;AAAA,IACP;AAEF,QAAM,MACJ,YACC,QAAQ,MAAM,QACX,MAAMC;AAAA,IAAI,MACN,QAAK,EAAE,SAAS,wBAAwB,aAAa,6BAA6B,CAAC;AAAA,EACvF,IACA,KAAK,8CAA8C,KAAK,WAAW;AACzE,QAAM,SAAS,KAAK,UAAU;AAE9B,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,aAAa,YAAY,OAAO,KAAK,MAAM;AACpE,OAAG,QAAQ,aAAa,GAAG,KAAK,MAAM,IAAI;AAC1C,OAAG,KAAK;AACR,QAAI,IAAI,WAAW;AACjB,SAAG,KAAK,wDAAwD;AAChE,SAAG,KAAK,IAAI,SAAS;AACrB,SAAG,KAAK;AAAA,IACV;AACA,QAAI,IAAI,YAAY;AAClB,SAAG,KAAK,qBAAqB;AAC7B,SAAG,GAAG,OAAO,IAAI,UAAU;AAC3B,UAAI,IAAI,OAAQ,IAAG,GAAG,UAAU,IAAI,MAAM;AAC1C,SAAG,KAAK;AAAA,IACV;AACA,QAAI,IAAI,KAAM,IAAG,IAAI,IAAI,IAAI;AAC7B,QAAI,QAAQ;AAEV,YAAM,kBAAkB,EAAE,GAAG,OAAO,GAAG,QAAQ,IAAI,CAAC;AAAA,IACtD;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAeD,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAeC,KAAO,IAA2C;AAC/D,QAAM,IAAI,MAAM,GAAG;AACnB,MAAIC,UAAS,CAAC,GAAG;AACf,IAAE,UAAO,YAAY;AACrB,YAAQ,KAAK,KAAK,EAAE;AAAA,EACtB;AACA,SAAO;AACT;;;ACvFA,SAAS,kBAAAC,uBAAuC;AAIhD,IAAM,SAAuB,CAAC,UAAU,QAAQ,MAAM;AAEtD,eAAsB,YACpB,MACA,MACe;AACf,MAAI,CAAC,KAAM,MAAK,kDAAkD,KAAK,WAAW;AAElF,QAAM,UAAU,KAAK,SAAS,KAAK,OAAO,MAAM,GAAG,IAAI,CAAC,UAAU,MAAM,GACrE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,EACjC,OAAO,CAAC,MAAwB,OAAoB,SAAS,CAAC,CAAC;AAClE,MAAI,OAAO,WAAW;AACpB,SAAK,iCAAiC,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,WAAW;AAE7E,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,IAAI,MAAM,OAAO,OAAO,OAAO,MAAM;AAAA,MACzC;AAAA,MACA,eAAe,KAAK,WAAW,KAAK,UAAU,IAAI,KAAK,UAAU;AAAA,IACnE,CAAC;AACD,OAAG;AAAA,MACD,YAAY,EAAE,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,IAAI,EAAE,YAAY,iBAAc,EAAE,UAAU,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE;AAAA,IAC5G;AACA,OAAG,KAAK;AACR,OAAG,KAAK,EAAE,KAAK;AACf,OAAG,KAAK;AACR,OAAG;AAAA,MACD;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAeC,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YAA2B;AAC/C,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,OAAO,KAAK;AACxC,QAAI,OAAO,WAAW,GAAG;AACvB,SAAG,KAAK,4BAA4B;AACpC;AAAA,IACF;AACA,OAAG,KAAK;AACR,eAAW,KAAK,QAAQ;AACtB,SAAG;AAAA,QACD,EAAE;AAAA,QACF,GAAG,EAAE,MAAM,eAAO,EAAE,OAAO,KAAK,GAAG,CAAC,GAC/B,EAAE,YAAY,iBAAc,EAAE,UAAU,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,GAC3D,EAAE,aAAa,cAAW,EAAE,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK,kBAAe;AAAA,MAC9E;AACA,SAAG,IAAI,QAAQ,EAAE,EAAE,EAAE;AAAA,IACvB;AACA,OAAG,KAAK;AAAA,EACV,SAAS,KAAK;AACZ,QAAI,eAAeA,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,YAAY,IAAuC;AACvE,MAAI,CAAC,GAAI,MAAK,oDAAoD,KAAK,WAAW;AAClF,QAAM,EAAE,OAAO,IAAI,MAAM,eAAe;AACxC,MAAI;AACF,UAAM,OAAO,OAAO,OAAO,EAAE;AAC7B,OAAG,QAAQ,WAAW,EAAE,GAAG;AAAA,EAC7B,SAAS,KAAK;AACZ,QAAI,eAAeA,gBAAgB,MAAK,IAAI,OAAO;AACnD,UAAM;AAAA,EACR;AACF;;;AC1EA,SAAS,mBAAmB;AAI5B,eAAsB,SAAwB;AAC5C,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,eAAe;AACrD,MAAI;AAEF,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ;AACzC,OAAG,KAAK;AACR,OAAG,GAAG,QAAQ,IAAI,KAAK,SAAS,IAAI,KAAK,EAAE;AAC3C,OAAG,GAAG,WAAW,IAAI,KAAK,EAAE;AAC5B,QAAI,aAAa,cAAc,WAAW,OAAO,GAAG;AAClD,SAAG,GAAG,QAAQ,0BAA0B,IAAI,OAAO,KAAK,IAAI,KAAK,WAAW,GAAG;AAAA,IACjF;AACA,QAAI,IAAI,cAAc,WAAW,GAAG;AAClC,SAAG,GAAG,gBAAgB,yCAAoC;AAAA,IAC5D,OAAO;AACL,YAAM,SACH,aAAa,gBACZ,IAAI,cAAc;AAAA,QAChB,CAAC,MAAM,EAAE,OAAO,YAAY,gBAAgB,EAAE,SAAS,YAAY;AAAA,MACrE,KACF,IAAI,cAAc,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,KACnD,IAAI,cAAc,CAAC;AACrB,iBAAW,KAAK,IAAI,eAAe;AACjC,cAAM,OAAO,EAAE,OAAO,QAAQ,KAAK,YAAO;AAC1C,WAAG,GAAG,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG;AAAA,MACnD;AAAA,IACF;AACA,OAAG,GAAG,SAAS,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,QAAQ;AACpE,OAAG,KAAK;AAAA,EACV,SAAS,KAAK;AACZ,QAAI,YAAY,GAAG,EAAG,MAAK,8CAA8C,KAAK,YAAY;AAC1F,UAAM;AAAA,EACR;AACF;;;AXzBA,IAAM,UAAU;AAEhB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,QAAQ,EACb,YAAY,gEAAgE,EAC5E,QAAQ,SAAS,eAAe;AAEnC,QACG,QAAQ,OAAO,EACf,YAAY,4DAA4D,EACxE,OAAO,iBAAiB,EACxB,OAAO,uBAAuB,EAC9B,OAAO,gBAAgB,4CAA4C,EACnE,OAAO,mBAAmB,4CAA4C,EACtE,OAAO,CAAC,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC,CAAC;AAE1C,QACG,QAAQ,QAAQ,EAChB,YAAY,2BAA2B,EACvC,OAAO,MAAM,IAAI,MAAM,CAAC;AAE3B,QACG,QAAQ,QAAQ,EAChB,YAAY,2CAA2C,EACvD,OAAO,MAAM,IAAI,MAAM,CAAC;AAE3B,QACG,QAAQ,MAAM,EACd,YAAY,qCAAqC,EACjD,OAAO,iBAAiB,YAAY,EACpC,OAAO,qBAAqB,0BAA0B,EACtD,OAAO,uBAAuB,6BAA6B,EAC3D,OAAO,aAAa,sCAAsC,EAC1D,OAAO,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC;AAEzC,QACG,QAAQ,QAAQ,EAChB,YAAY,+CAA+C,EAC3D,OAAO,cAAc,mCAAmC,EACxD,OAAO,eAAe,gDAAgD,EACtE,OAAO,eAAe,sCAAsC,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,CAAC,EACzF,OAAO,CAAC,SAAS,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;AAE3C,QACG,QAAQ,MAAM,EACd,YAAY,uBAAuB,EACnC,OAAO,gBAAgB,kBAAkB,EACzC,OAAO,eAAe,kBAAkB,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,CAAC,EACrE,OAAO,cAAc,0CAA0C,EAC/D,OAAO,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC;AAEzC,IAAM,MAAM,QAAQ,QAAQ,KAAK,EAAE,YAAY,0CAA0C;AACzF,IACG,QAAQ,MAAM,EACd,YAAY,kDAAkD,EAC9D,OAAO,YAAY,EACnB,OAAO,CAAC,SAAS,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC;AAC5C,IACG,QAAQ,gBAAgB,EACxB,YAAY,iCAAiC,EAC7C,OAAO,YAAY,EACnB,OAAO,CAAC,OAAO,SAAS,IAAI,MAAM,OAAO,OAAO,IAAI,CAAC,CAAC;AACzD,IACG,QAAQ,cAAc,EACtB,YAAY,8BAA8B,EAC1C,OAAO,YAAY,EACnB,OAAO,CAAC,MAAM,SAAS,IAAI,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC;AAEtD,QACG,QAAQ,SAAS,EACjB,YAAY,8CAA8C,EAC1D,OAAO,YAAY,EACnB,OAAO,CAAC,SAAS,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC;AAE5C,QACG,QAAQ,MAAM,EACd,YAAY,qCAAqC,EACjD,OAAO,MAAM,IAAI,IAAI,CAAC;AAEzB,IAAM,QAAQ,QACX,QAAQ,OAAO,EACf,YAAY,2DAA2D;AAC1E,MACG,QAAQ,eAAe,EACvB,YAAY,8CAAyC,EACrD,OAAO,mBAAmB,qCAAqC,aAAa,EAC5E,OAAO,oBAAoB,uBAAuB,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,CAAC,EAC/E,OAAO,CAAC,MAAM,SAAS,IAAI,MAAM,YAAY,MAAM,IAAI,CAAC,CAAC;AAC5D,MACG,QAAQ,MAAM,EACd,YAAY,kBAAkB,EAC9B,OAAO,MAAM,IAAI,SAAS,CAAC;AAC9B,MACG,QAAQ,aAAa,EACrB,YAAY,gBAAgB,EAC5B,OAAO,CAAC,OAAO,IAAI,MAAM,YAAY,EAAE,CAAC,CAAC;AAE5C,QACG,QAAQ,gBAAgB,EACxB,YAAY,yCAAyC,EACrD,OAAO,qBAAqB,oBAAoB,MAAM,EACtD,OAAO,YAAY,EACnB,OAAO,CAAC,SAAS,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC;AAE3D,QAAQ,WAAW,EAAE,MAAM,CAAC,QAAQ;AAClC,KAAG,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AACzD,UAAQ,KAAK,KAAK,OAAO;AAC3B,CAAC;AAED,eAAe,IAAI,IAAwC;AACzD,MAAI;AACF,UAAM,GAAG;AAAA,EACX,SAAS,KAAK;AACZ,QAAI,eAAe,UAAU;AAC3B,SAAG,MAAM,IAAI,OAAO;AACpB,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,OAAG,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AACzD,YAAQ,KAAK,KAAK,OAAO;AAAA,EAC3B;AACF;","names":["env","p","buildProjectConfig","loadProjectConfig","saveProjectConfig","loadProjectConfig","buildProjectConfig","saveProjectConfig","p","isCancel","RoxyonApiError","password","RoxyonApiError","isCancel","RoxyonApiError","RoxyonApiError","p","isCancel","RoxyonApiError","RoxyonApiError","ask","isCancel","RoxyonApiError","RoxyonApiError"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/deploy.ts","../src/context.ts","../src/config.ts","../src/ui.ts","../src/commands/env.ts","../src/commands/init.ts","../src/commands/login.ts","../src/commands/logs.ts","../src/commands/misc.ts","../src/commands/token.ts","../src/commands/whoami.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { deploy } from './commands/deploy.js';\nimport { envPull, envRm, envSet } from './commands/env.js';\nimport { init } from './commands/init.js';\nimport { login, logout } from './commands/login.js';\nimport { logs } from './commands/logs.js';\nimport { link, open, restart } from './commands/misc.js';\nimport { tokenCreate, tokenList, tokenRevoke } from './commands/token.js';\nimport { whoami } from './commands/whoami.js';\nimport { CliError, EXIT, ui } from './ui.js';\n\nconst VERSION = '0.1.0';\n\nconst program = new Command();\n\nprogram\n .name('roxyon')\n .description('Deploy LumenJS apps and web projects to Roxyon infrastructure.')\n .version(VERSION, '-v, --version');\n\nprogram\n .command('login')\n .description('Sign in to Roxyon (email + password, with OTP if required)')\n .option('--email <email>')\n .option('--password <password>')\n .option('--otp <code>', 'one-time code, for non-interactive step-up')\n .option('--token <token>', 'use a session/personal token directly (CI)')\n .action((opts) => run(() => login(opts)));\n\nprogram\n .command('logout')\n .description('Remove stored credentials')\n .action(() => run(logout));\n\nprogram\n .command('whoami')\n .description('Show the signed-in user and subscriptions')\n .action(() => run(whoami));\n\nprogram\n .command('init')\n .description('Create roxyon.json for this project')\n .option('--host <host>', 'route host')\n .option('--folder <folder>', 'sub-path / source folder')\n .option('--runtime <runtime>', 'lumen | node | python | php')\n .option('-y, --yes', 'accept detected defaults, no prompts')\n .action((opts) => run(() => init(opts)));\n\nprogram\n .command('deploy')\n .description('Build (if configured) and deploy this project')\n .option('--no-build', 'skip the configured build command')\n .option('--no-follow', 'return once the build is queued (app runtimes)')\n .option('--lines <n>', 'log lines to stream while building', (v) => Number.parseInt(v, 10))\n .action((opts) => run(() => deploy(opts)));\n\nprogram\n .command('logs')\n .description('Show application logs')\n .option('-f, --follow', 'stream new lines')\n .option('--lines <n>', 'how many lines', (v) => Number.parseInt(v, 10))\n .option('--app <id>', 'application id (defaults to roxyon.json)')\n .action((opts) => run(() => logs(opts)));\n\nconst env = program.command('env').description('Manage application environment variables');\nenv\n .command('pull')\n .description('Print the current environment as KEY=value lines')\n .option('--app <id>')\n .action((opts) => run(() => envPull(opts)));\nenv\n .command('set <pairs...>')\n .description('Set one or more KEY=value pairs')\n .option('--app <id>')\n .action((pairs, opts) => run(() => envSet(pairs, opts)));\nenv\n .command('rm <keys...>')\n .description('Remove one or more variables')\n .option('--app <id>')\n .action((keys, opts) => run(() => envRm(keys, opts)));\n\nprogram\n .command('restart')\n .description('Restart the application process (no rebuild)')\n .option('--app <id>')\n .action((opts) => run(() => restart(opts)));\n\nprogram\n .command('open')\n .description(\"Open the project's URL in a browser\")\n .action(() => run(open));\n\nconst token = program\n .command('token')\n .description('Manage personal access tokens (for CI and the MCP server)');\ntoken\n .command('create <name>')\n .description('Create a token — prints the secret once')\n .option('--scopes <list>', 'comma-separated: deploy,logs,read,billing:order', 'deploy,logs')\n .option('--expires <days>', 'expire after N days', (v) => Number.parseInt(v, 10))\n .option('--budget <usd>', 'billing:order: most it may order per month, USD', (v) =>\n Number.parseFloat(v),\n )\n .option('--skus <list>', 'billing:order: plan codes it may order, e.g. SCALE-S,LAUNCH-M')\n .action((name, opts) => run(() => tokenCreate(name, opts)));\ntoken\n .command('list')\n .description('List your tokens')\n .action(() => run(tokenList));\ntoken\n .command('revoke <id>')\n .description('Revoke a token')\n .action((id) => run(() => tokenRevoke(id)));\n\nprogram\n .command('link [repoUrl]')\n .description('Connect a git remote for push-to-deploy')\n .option('--branch <branch>', 'branch to deploy', 'main')\n .option('--app <id>')\n .action((repoUrl, opts) => run(() => link(repoUrl, opts)));\n\nprogram.parseAsync().catch((err) => {\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(EXIT.failure);\n});\n\nasync function run(fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (err) {\n if (err instanceof CliError) {\n ui.error(err.message);\n process.exit(err.exitCode);\n }\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(EXIT.failure);\n }\n}\n","import * as p from '@clack/prompts';\nimport { DeployError, deployProject } from '@roxyon/deploy-core';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface DeployOptions {\n follow?: boolean;\n build?: boolean;\n lines?: number;\n}\n\nconst CODE: Record<DeployError['code'], number> = {\n 'no-config': EXIT.configError,\n auth: EXIT.authRequired,\n 'bad-host': EXIT.configError,\n 'build-failed': EXIT.failure,\n 'no-build-output': EXIT.failure,\n 'upload-failed': EXIT.failure,\n 'create-failed': EXIT.failure,\n};\n\nexport async function deploy(opts: DeployOptions): Promise<void> {\n const { roxyon, credentials } = await requireSession();\n const spin = p.spinner();\n let spinning = false;\n\n const reporter = {\n step: (msg: string) => {\n if (spinning) spin.message(msg);\n else {\n spin.start(msg);\n spinning = true;\n }\n },\n log: (line: string) => ui.dim(` ${line}`),\n };\n\n try {\n const outcome = await deployProject({\n cwd: process.cwd(),\n roxyon,\n preferredSubscription: credentials?.subscription,\n build: opts.build,\n follow: opts.follow,\n reporter,\n });\n\n if (outcome.kind === 'static' && outcome.ok) {\n spin.stop('Deployed.');\n ui.success(`${outcome.url} is live (${outcome.files} files).`);\n return;\n }\n if (outcome.kind === 'app' && outcome.ok) {\n spin.stop(\n outcome.status === 'running'\n ? `Live — revision ${outcome.revision} running.`\n : `Build queued (revision ${outcome.revision}).`,\n );\n if (outcome.url) ui.success(outcome.url);\n return;\n }\n // app, not ok\n spin.stop('Deploy failed.');\n if ('error' in outcome && outcome.error) {\n ui.line();\n ui.error(outcome.error);\n }\n process.exitCode = EXIT.failure;\n } catch (err) {\n if (spinning) spin.stop('Failed.');\n if (err instanceof DeployError) fail(err.message, CODE[err.code]);\n throw err;\n }\n}\n","import { Roxyon } from '@roxyon/api-client';\nimport { type Credentials, endpointsFromEnv, loadCredentials, tokenFromEnv } from './config.js';\nimport { EXIT, fail } from './ui.js';\n\nexport interface Session {\n roxyon: Roxyon;\n /** Present when authenticated via a stored login (not a bare CI token). */\n credentials?: Credentials;\n}\n\n/** Build a client from a `ROXYON_TOKEN` env var or the stored login. Fails if neither. */\nexport async function requireSession(): Promise<Session> {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n const envToken = tokenFromEnv();\n if (envToken) {\n return {\n roxyon: new Roxyon({ sessionToken: envToken, baseUrl: apiUrl, consoleUrl: consoleUrl }),\n };\n }\n\n const creds = await loadCredentials();\n if (!creds?.sessionToken) {\n fail('Not signed in. Run `roxyon login` (or set ROXYON_TOKEN for CI).', EXIT.authRequired);\n }\n return {\n roxyon: new Roxyon({ sessionToken: creds.sessionToken, baseUrl: apiUrl, consoleUrl }),\n credentials: creds,\n };\n}\n\n/** A client with no user auth — for the login flow itself. */\nexport function anonymousRoxyon(): Roxyon {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n return new Roxyon({ baseUrl: apiUrl, consoleUrl });\n}\n","/**\n * All config lives in `@roxyon/deploy-core` so the CLI and the MCP server share\n * one implementation. This module just re-exports it.\n */\nexport {\n buildProjectConfig,\n clearCredentials,\n type Credentials,\n credentialsPath,\n type Endpoints,\n endpointsFromEnv,\n loadCredentials,\n loadProjectConfig,\n type ProjectConfig,\n projectConfigPath,\n saveCredentials,\n saveProjectConfig,\n tokenFromEnv,\n} from '@roxyon/deploy-core';\n","import pc from 'picocolors';\n\nexport const ui = {\n info: (msg: string) => process.stdout.write(`${pc.cyan('›')} ${msg}\\n`),\n success: (msg: string) => process.stdout.write(`${pc.green('✓')} ${msg}\\n`),\n warn: (msg: string) => process.stderr.write(`${pc.yellow('!')} ${msg}\\n`),\n error: (msg: string) => process.stderr.write(`${pc.red('✗')} ${msg}\\n`),\n line: (msg = '') => process.stdout.write(`${msg}\\n`),\n dim: (msg: string) => process.stdout.write(`${pc.dim(msg)}\\n`),\n kv: (key: string, value: string) =>\n process.stdout.write(` ${pc.dim(key.padEnd(14))} ${value}\\n`),\n};\n\n/** Exit codes — kept stable for scripting / CI. */\nexport const EXIT = {\n ok: 0,\n failure: 1,\n authRequired: 2,\n configError: 3,\n} as const;\n\nexport class CliError extends Error {\n readonly exitCode: number;\n constructor(message: string, exitCode: number = EXIT.failure) {\n super(message);\n this.name = 'CliError';\n this.exitCode = exitCode;\n }\n}\n\nexport function fail(message: string, exitCode: number = EXIT.failure): never {\n throw new CliError(message, exitCode);\n}\n","import { RoxyonApiError, formatEnv } from '@roxyon/api-client';\nimport { loadProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nasync function resolveApp(explicit?: string): Promise<string> {\n const appId = explicit ?? (await loadProjectConfig())?.application;\n if (!appId)\n fail('No application. Pass --app <id> or deploy this project first.', EXIT.configError);\n return appId;\n}\n\nexport async function envPull(opts: { app?: string }): Promise<void> {\n const appId = await resolveApp(opts.app);\n const { roxyon } = await requireSession();\n try {\n const env = await roxyon.applications.getEnv(appId);\n ui.line(formatEnv(env) || '# (no environment variables set)');\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function envSet(pairs: string[], opts: { app?: string }): Promise<void> {\n if (pairs.length === 0)\n fail('Nothing to set. Usage: roxyon env set KEY=value [KEY2=value2]', EXIT.configError);\n const appId = await resolveApp(opts.app);\n\n const set: Record<string, string> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf('=');\n if (eq < 1) fail(`\"${pair}\" is not KEY=value.`, EXIT.configError);\n const key = pair.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) fail(`Invalid env key \"${key}\".`, EXIT.configError);\n if (key === 'PORT' || key === 'HOST') {\n ui.warn(`${key} is set by the platform — ignoring.`);\n continue;\n }\n set[key] = pair.slice(eq + 1);\n }\n\n const { roxyon } = await requireSession();\n try {\n const r = await roxyon.applications.setEnv(appId, { set });\n ui.success(`Updated ${r.changed.join(', ') || 'nothing'}. Run \\`roxyon deploy\\` to apply.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function envRm(keys: string[], opts: { app?: string }): Promise<void> {\n if (keys.length === 0)\n fail('Nothing to remove. Usage: roxyon env rm KEY [KEY2]', EXIT.configError);\n const appId = await resolveApp(opts.app);\n const { roxyon } = await requireSession();\n try {\n const r = await roxyon.applications.setEnv(appId, { remove: keys });\n ui.success(`Removed ${r.changed.join(', ') || 'nothing'}. Run \\`roxyon deploy\\` to apply.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { basename } from 'node:path';\nimport * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport type { RuntimeName } from '@roxyon/api-client';\nimport {\n buildProjectConfig,\n detectRuntime,\n loadProjectConfig,\n saveProjectConfig,\n} from '@roxyon/deploy-core';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface InitOptions {\n host?: string;\n folder?: string;\n runtime?: RuntimeName;\n yes?: boolean;\n}\n\nexport async function init(opts: InitOptions): Promise<void> {\n const cwd = process.cwd();\n const existing = await loadProjectConfig(cwd);\n if (existing && !opts.yes) {\n const overwrite = await ask(() =>\n p.confirm({ message: 'roxyon.json already exists — overwrite it?', initialValue: false }),\n );\n if (!overwrite) return;\n }\n\n const { roxyon, credentials } = await requireSession();\n const user = await roxyon.auth.me();\n const sub = await roxyon.subscriptions.resolve(user.objectId, credentials?.subscription);\n const domains = await roxyon.domains.list(sub.objectId);\n if (domains.length === 0) {\n fail(\n 'This subscription has no hosts yet. Add a domain in the console, then run `roxyon init` again.',\n EXIT.configError,\n );\n }\n\n const detected = await detectRuntime(cwd);\n ui.info(`Detected runtime: ${detected.runtime} — ${detected.reason}`);\n\n const runtime: RuntimeName = opts.runtime\n ? opts.runtime\n : opts.yes\n ? detected.runtime\n : await ask<RuntimeName>(() =>\n p.select({\n message: 'Runtime',\n initialValue: detected.runtime,\n options: [\n { value: 'lumen', label: 'LumenJS (static SPA, no server)' },\n { value: 'node', label: 'Node.js app' },\n { value: 'python', label: 'Python app' },\n { value: 'php', label: 'PHP app' },\n ],\n }),\n );\n\n const host: string =\n opts.host ??\n (opts.yes\n ? (domains[0]?.Name ?? fail('No host available.', EXIT.configError))\n : await ask<string>(() =>\n p.select({\n message: 'Host',\n options: domains.map((d) => ({ value: d.Name, label: d.Name })),\n }),\n ));\n\n const defaultFolder = basename(cwd).replace(/[^a-z0-9._-]/gi, '-');\n const folder =\n opts.folder ??\n (opts.yes\n ? runtime === 'lumen'\n ? ''\n : defaultFolder\n : await ask<string>(() =>\n p.text({\n message:\n runtime === 'lumen'\n ? 'Sub-path under the host root (blank = site root)'\n : 'Folder under the host (source location)',\n placeholder: runtime === 'lumen' ? '(root)' : defaultFolder,\n defaultValue: runtime === 'lumen' ? '' : defaultFolder,\n }),\n ));\n\n const config = buildProjectConfig({\n cwd,\n runtime,\n host,\n folder,\n name: basename(cwd),\n start: detected.start,\n });\n\n const path = await saveProjectConfig(config, cwd);\n ui.success(`Wrote ${path}`);\n ui.line();\n ui.dim(JSON.stringify(config, null, 2));\n ui.line();\n ui.info('Next: `roxyon deploy`');\n}\n\nasync function ask<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const v = await fn();\n if (isCancel(v)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return v as T;\n}\n","import * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport { RoxyonApiError } from '@roxyon/api-client';\nimport { type Credentials, clearCredentials, loadCredentials, saveCredentials } from '../config.js';\nimport { anonymousRoxyon } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface LoginOptions {\n email?: string;\n password?: string;\n token?: string;\n otp?: string;\n}\n\nexport async function login(opts: LoginOptions): Promise<void> {\n const roxyon = anonymousRoxyon();\n\n // Non-interactive: a token was handed in directly.\n if (opts.token) {\n roxyon.client.setSessionToken(opts.token);\n const user = await roxyon.auth.me().catch((e) => {\n fail(`That token did not authenticate: ${(e as Error).message}`, EXIT.authRequired);\n });\n await persist({ sessionToken: opts.token, userId: user.objectId, email: user.Email });\n ui.success(`Signed in as ${user.Email ?? user.objectId} (via --token).`);\n return;\n }\n\n const interactive = process.stdin.isTTY && !opts.password;\n\n const email =\n opts.email ??\n (interactive\n ? await prompt(() =>\n p.text({\n message: 'Email',\n validate: (v) => (v.includes('@') ? undefined : 'Enter an email'),\n }),\n )\n : fail(\n 'Provide --email (and --password), or run in an interactive terminal.',\n EXIT.configError,\n ));\n\n const password =\n opts.password ??\n (interactive\n ? await prompt(() => p.password({ message: 'Password' }))\n : fail('Provide --password.', EXIT.configError));\n\n const spin = p.spinner();\n spin.start('Signing in');\n try {\n let result = await roxyon.auth.login(email, password, { via: 'cli' });\n\n if (result.stepUpRequired) {\n spin.stop('A one-time code was sent to you.');\n const code =\n opts.otp ??\n (interactive\n ? await prompt(() => p.text({ message: 'One-time code' }))\n : fail('This account requires OTP — pass --otp <code>.', EXIT.authRequired));\n spin.start('Verifying code');\n result = await roxyon.auth.verifyOtp(result.challengeId ?? '', code);\n }\n\n roxyon.client.setSessionToken(result.sessionToken);\n const user = await roxyon.auth.me();\n await persist({\n sessionToken: result.sessionToken,\n refreshToken: result.refreshToken,\n userId: user.objectId,\n email: user.Email,\n });\n spin.stop(`Signed in as ${user.Email ?? user.objectId}.`);\n ui.dim('Token stored in ~/.roxyon/config.json (permissions 0600).');\n } catch (err) {\n spin.stop('Sign-in failed.');\n if (err instanceof RoxyonApiError) fail(err.message, EXIT.authRequired);\n throw err;\n }\n}\n\nexport async function logout(): Promise<void> {\n const creds = await loadCredentials();\n await clearCredentials();\n ui.success(creds ? `Signed out ${creds.email ?? creds.userId}.` : 'Nothing to sign out.');\n}\n\nasync function persist(partial: Omit<Credentials, 'savedAt'>): Promise<void> {\n await saveCredentials({ ...partial, savedAt: new Date().toISOString() });\n}\n\nasync function prompt<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const value = await fn();\n if (isCancel(value)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return value as T;\n}\n","import { RoxyonApiError } from '@roxyon/api-client';\nimport { loadProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport interface LogsOptions {\n follow?: boolean;\n lines?: number;\n app?: string;\n}\n\nexport async function logs(opts: LogsOptions): Promise<void> {\n const appId = opts.app ?? (await loadProjectConfig())?.application;\n if (!appId) {\n fail(\n 'No application. Pass --app <id>, or run from a project whose roxyon.json has one.',\n EXIT.configError,\n );\n }\n\n const { roxyon } = await requireSession();\n const lines = opts.lines ?? 100;\n\n if (!opts.follow) {\n for (const l of await fetchLogs(\n roxyon.applications.logs.bind(roxyon.applications),\n appId,\n lines,\n )) {\n ui.line(l);\n }\n return;\n }\n\n ui.dim(`Following ${appId} — Ctrl-C to stop.`);\n let seen = new Set<string>();\n const tick = async () => {\n try {\n for (const l of await roxyon.applications.logs(appId, lines)) {\n if (l && !seen.has(l)) {\n seen.add(l);\n ui.line(l);\n }\n }\n if (seen.size > 4000) seen = new Set([...seen].slice(-2000));\n } catch (err) {\n ui.warn((err as Error).message);\n }\n };\n await tick();\n const timer = setInterval(tick, 7000);\n process.on('SIGINT', () => {\n clearInterval(timer);\n process.exit(EXIT.ok);\n });\n}\n\nasync function fetchLogs(\n fn: (id: string, n: number) => Promise<string[]>,\n appId: string,\n lines: number,\n): Promise<string[]> {\n try {\n return await fn(appId, lines);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { spawn } from 'node:child_process';\nimport { platform } from 'node:os';\nimport * as p from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport { RoxyonApiError } from '@roxyon/api-client';\nimport { loadProjectConfig, saveProjectConfig } from '../config.js';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport async function restart(opts: { app?: string }): Promise<void> {\n const appId = opts.app ?? (await loadProjectConfig())?.application;\n if (!appId)\n fail('No application. Pass --app <id> or deploy this project first.', EXIT.configError);\n const { roxyon } = await requireSession();\n try {\n await roxyon.applications.restart(appId);\n ui.success('Restart queued.');\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function open(): Promise<void> {\n const config = await loadProjectConfig();\n if (!config) fail('No roxyon.json here.', EXIT.configError);\n const url = `https://${config.host}${config.folder ? `/${config.folder}` : ''}`;\n const cmd = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';\n spawn(cmd, [url], { stdio: 'ignore', detached: true, shell: platform() === 'win32' }).unref();\n ui.info(`Opening ${url}`);\n}\n\nexport async function link(\n repoUrl: string | undefined,\n opts: { branch?: string; app?: string },\n): Promise<void> {\n const config = await loadProjectConfig();\n const appId = opts.app ?? config?.application;\n if (!appId)\n fail(\n 'Deploy the project once first so an application exists, then `roxyon link`.',\n EXIT.configError,\n );\n\n const url =\n repoUrl ??\n (process.stdin.isTTY\n ? await ask(() =>\n p.text({ message: 'Git remote (SSH URL)', placeholder: 'git@github.com:you/app.git' }),\n )\n : fail('Pass the git remote URL: roxyon link <url>', EXIT.configError));\n const branch = opts.branch ?? 'main';\n\n const { roxyon } = await requireSession();\n try {\n const res = await roxyon.applications.repoConnect(appId, url, branch);\n ui.success(`Connected ${url} (${branch}).`);\n ui.line();\n if (res.deployKey) {\n ui.info('Add this deploy key to the repo (read-only is enough):');\n ui.line(res.deployKey);\n ui.line();\n }\n if (res.webhookUrl) {\n ui.info('Add a push webhook:');\n ui.kv('URL', res.webhookUrl);\n if (res.secret) ui.kv('Secret', res.secret);\n ui.line();\n }\n if (res.hint) ui.dim(res.hint);\n if (config) {\n // Record the remote so `roxyon deploy` can note that pushes auto-deploy.\n await saveProjectConfig({ ...config }, process.cwd());\n }\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nasync function ask<T>(fn: () => Promise<T | symbol>): Promise<T> {\n const v = await fn();\n if (isCancel(v)) {\n p.cancel('Cancelled.');\n process.exit(EXIT.ok);\n }\n return v as T;\n}\n","import { RoxyonApiError, type TokenScope } from '@roxyon/api-client';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nconst SCOPES: TokenScope[] = ['deploy', 'logs', 'read', 'billing:order'];\n\nexport async function tokenCreate(\n name: string | undefined,\n opts: { scopes?: string; expires?: number; budget?: number; skus?: string },\n): Promise<void> {\n if (!name) fail('A name is required: roxyon token create <name>', EXIT.configError);\n\n const scopes = (opts.scopes ? opts.scopes.split(',') : ['deploy', 'logs'])\n .map((s) => s.trim().toLowerCase())\n .filter((s): s is TokenScope => (SCOPES as string[]).includes(s));\n if (scopes.length === 0)\n fail(`--scopes must be a subset of: ${SCOPES.join(', ')}`, EXIT.configError);\n\n const ordering = scopes.includes('billing:order');\n if (ordering && !(opts.budget && opts.budget > 0))\n fail('A billing:order token needs --budget <USD per month>', EXIT.configError);\n\n const { roxyon } = await requireSession();\n try {\n const t = await roxyon.tokens.create(name, {\n scopes,\n expiresInDays: opts.expires && opts.expires > 0 ? opts.expires : undefined,\n ...(ordering\n ? {\n monthlyBudgetUSD: opts.budget,\n allowedSkus: opts.skus ? opts.skus.split(',').map((x) => x.trim().toUpperCase()) : [],\n }\n : {}),\n });\n ui.success(\n `Created \"${t.name}\" (${t.scopes.join(', ')})${t.expiresAt ? ` · expires ${t.expiresAt.slice(0, 10)}` : ''}`,\n );\n ui.line();\n ui.line(t.token);\n ui.line();\n ui.dim(\n 'Copy it now — it will not be shown again. Use it as ROXYON_TOKEN in CI or the MCP server.',\n );\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function tokenList(): Promise<void> {\n const { roxyon } = await requireSession();\n try {\n const tokens = await roxyon.tokens.list();\n if (tokens.length === 0) {\n ui.info('No personal access tokens.');\n return;\n }\n ui.line();\n for (const t of tokens) {\n ui.kv(\n t.name,\n `${t.prefix}… · ${t.scopes.join(',')}` +\n `${t.expiresAt ? ` · expires ${t.expiresAt.slice(0, 10)}` : ''}` +\n `${t.lastUsedAt ? ` · used ${t.lastUsedAt.slice(0, 10)}` : ' · never used'}`,\n );\n ui.dim(` id ${t.id}`);\n }\n ui.line();\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n\nexport async function tokenRevoke(id: string | undefined): Promise<void> {\n if (!id) fail('A token id is required: roxyon token revoke <id>', EXIT.configError);\n const { roxyon } = await requireSession();\n try {\n await roxyon.tokens.revoke(id);\n ui.success(`Revoked ${id}.`);\n } catch (err) {\n if (err instanceof RoxyonApiError) fail(err.message);\n throw err;\n }\n}\n","import { isAuthError } from '@roxyon/api-client';\nimport { requireSession } from '../context.js';\nimport { EXIT, fail, ui } from '../ui.js';\n\nexport async function whoami(): Promise<void> {\n const { roxyon, credentials } = await requireSession();\n try {\n // One call — works with a session token or a PAT.\n const ctx = await roxyon.account.context();\n ui.line();\n ui.kv('User', ctx.user.email || ctx.user.id);\n ui.kv('User ID', ctx.user.id);\n if (credentials?.sessionToken?.startsWith('roxp_')) {\n ui.kv('Auth', `personal access token (${ctx.scopes.join(', ') || 'no scopes'})`);\n }\n if (ctx.subscriptions.length === 0) {\n ui.kv('Subscription', '(none — add a plan in the console)');\n } else {\n const active =\n (credentials?.subscription &&\n ctx.subscriptions.find(\n (s) => s.id === credentials.subscription || s.name === credentials.subscription,\n )) ||\n ctx.subscriptions.find((s) => s.status === 'active') ||\n ctx.subscriptions[0];\n for (const s of ctx.subscriptions) {\n const mark = s.id === active?.id ? '→ ' : ' ';\n ui.kv(`${mark}${s.name || s.id}`, s.status || '?');\n }\n }\n ui.kv('Hosts', ctx.domains.map((d) => d.name).join(', ') || '(none)');\n ui.line();\n } catch (err) {\n if (isAuthError(err)) fail('Session expired. Run `roxyon login` again.', EXIT.authRequired);\n throw err;\n }\n}\n"],"mappings":"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","names":["env","p","buildProjectConfig","loadProjectConfig","saveProjectConfig","loadProjectConfig","buildProjectConfig","saveProjectConfig","p","isCancel","RoxyonApiError","password","RoxyonApiError","isCancel","RoxyonApiError","RoxyonApiError","p","isCancel","RoxyonApiError","RoxyonApiError","ask","isCancel","RoxyonApiError","RoxyonApiError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roxyon/cli",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Deploy LumenJS apps and web projects to Roxyon infrastructure from anywhere — including AI assistants.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,8 +32,8 @@
32
32
  "@clack/prompts": "^0.7.0",
33
33
  "commander": "^12.1.0",
34
34
  "picocolors": "^1.1.1",
35
- "@roxyon/deploy-core": "0.3.0",
36
- "@roxyon/api-client": "0.3.0"
35
+ "@roxyon/api-client": "0.5.0",
36
+ "@roxyon/deploy-core": "0.3.2"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^20.16.11",