import { type Output } from '../output.js'; /** * `bitmagic reset-account` — put your own account back to never-seen-before, so * the first-run path can be walked again. * * Everything a new creator meets happens exactly once per identity: the install, * the device code, the terms notice, "no Bitmagic Pro subscription", Stripe * checkout, the first `bitmagic init` and its 500 sparks. Testing a change to * any of it used to mean finding a fresh Auth0 account. This deletes the account * server-side instead, so the next `bitmagic login` provisions it from scratch. * * The list starts at `npm install -g @bitmagic/cli`, which is why the reset ends * by removing the CLI as well. That was opt-in at first and it was the wrong * default: it made the step people actually wanted the one they had to remember, * and a reset that leaves the tool installed does not reproduce the state it * claims to. `--keep-cli` opts out, for resetting an account mid-session. * * ── Why this cannot touch prod ────────────────────────────────────────────── * * The endpoint behind it is not registered on the production api-server at all, * so the path does not exist there. This command refuses `--env prod` before it * opens a socket anyway: the server would answer with a status code, and a * sentence is a better thing to read than a 404. * * ── Why it asks ───────────────────────────────────────────────────────────── * * The confirmation wants the ENVIRONMENT NAME typed back, not a y/n. The whole * hazard here is running the right command against the wrong environment, and * "y" is the same keystroke whichever one you are pointed at. `--yes` skips it * for scripts, and a non-interactive shell must pass `--yes` explicitly rather * than have the prompt silently pass — an agent should not be able to delete a * creator's account by running a command it read in a doc. */ /** What the api-server says a reset would destroy. */ export interface ResetPreview { userId: string; email: string; publicId: string | null; games: number; sparkBalance: number; hasProSubscription: boolean; stripeSubscriptionId: string | null; hasProGrant: boolean; /** vip_users is keyed by email and survives the reset — worth saying out loud. */ vip: boolean; } export interface ResetAccountDeps { fetch: typeof globalThis.fetch; sleep: (ms: number) => Promise; /** Whether a human is at the keyboard; injected so the rule is testable. */ interactive: () => boolean; /** Reads one line of confirmation. */ ask: (question: string) => Promise; /** Removes the globally installed CLI. Returns false if it could not. */ uninstall: () => boolean; } export declare const defaultResetDeps: ResetAccountDeps; /** PURE. The lines shown before the confirmation. */ export declare function formatResetPreview(preview: ResetPreview, environmentName: string, removesCli: boolean): string; export interface ResetAccountOptions { env?: string; yes?: boolean; /** * Leave the globally installed CLI alone. Off by default — the install is the * FIRST step of the first-run experience this command exists to replay, so * removing it is part of the reset rather than an extra someone has to * remember. `--keep-cli` is for resetting the account mid-session without * having to reinstall to carry on. */ keepCli?: boolean; deps?: ResetAccountDeps; /** Test-only credentials-directory override, matching the rest of the CLI. */ baseDir?: string; } export interface ResetAccountResult { environment: string; userId: string; stripeSubscriptionCanceled: boolean; deleted: Record; credentialsCleared: boolean; cliUninstalled: boolean; } export declare function runResetAccount(options: ResetAccountOptions, output: Output): Promise; /** PURE. What to do next, given what the reset just did. */ export declare function formatNextSteps(result: ResetAccountResult): string; export declare const resetAccountCommand: import("citty").CommandDef<{ readonly env: { readonly type: "string"; readonly description: "Environment to reset in (dev, local). Never prod."; }; readonly yes: { readonly type: "boolean"; readonly description: "Skip the confirmation. Required in a non-interactive shell."; }; readonly 'keep-cli': { readonly type: "boolean"; readonly description: string; }; readonly json: { readonly type: "boolean"; readonly description: "Print the result as JSON on stdout; all progress goes to stderr."; }; }>;