/** * The Val login flow, as reusable primitives. * * This is an RFC 8628 device authorization grant. The shape that matters: * {@link ValDeviceAuthorization.deviceCode} is a secret this process holds and * polls with, while {@link ValDeviceAuthorization.userCode} is the short string * the human reads out of the terminal and types into a browser. Only the device * code can collect a token. * * Keep them apart. Show the user code; never print, log or put the device code * in a URL. An earlier version of this flow used one value for both jobs, which * meant anyone who saw the verification link could collect the token it led to. * * The CLI wraps these with terminal output, and `@valbuild/language-server` * wraps them with LSP `window/showDocument` and progress reporting. Neither the * polling nor the token handling is duplicated between them. * * Deliberately no `console` output and no `process.exit`: every failure is a * thrown {@link ValLoginError} so an embedder can decide how to surface it. */ export declare const DEFAULT_LOGIN_HOST = "https://admin.val.build"; export type ValLoginErrorCode = /** The server replied with something other than JSON. */ "unexpected-content-type" /** The server replied with JSON, but not the shape we expect. */ | "unexpected-response" /** The server returned a 5xx. */ | "server-error" /** The user declined the login in the browser. */ | "access-denied" /** The login was not approved before the code expired. */ | "expired" /** The user did not complete the login within the allotted time. */ | "timeout" /** The caller aborted the flow. */ | "aborted"; export declare class ValLoginError extends Error { readonly code: ValLoginErrorCode; readonly details?: string | undefined; constructor(code: ValLoginErrorCode, message: string, details?: string | undefined); } /** A login attempt that is waiting for the user to approve it in a browser. */ export type ValDeviceAuthorization = { /** * Secret. Polls for the token. Do not display, log or transmit anywhere but * the token endpoint. */ deviceCode: string; /** Short code for the user to compare and type. Safe to display. */ userCode: string; /** Where the user goes to enter {@link userCode}. */ verificationUri: string; /** {@link verificationUri} with the code prefilled, for convenience. */ verificationUriComplete: string; /** Seconds until the code stops being approvable. */ expiresInSeconds: number; /** Minimum seconds between polls, per the server. */ intervalSeconds: number; }; export type ValLoginResult = { profile: { email: string; }; pat: string; }; /** * Begin a login attempt. The caller is responsible for getting the user code * and verification URL in front of the user. */ export declare function startValLogin(options?: { host?: string; deviceName?: string; }): Promise; /** Fallbacks for a server that omits the optional RFC 8628 timing fields. */ export declare const DEFAULT_LOGIN_EXPIRES_IN_SECONDS = 600; export declare const DEFAULT_LOGIN_POLL_INTERVAL_SECONDS = 5; /** * Poll until the user approves the login in their browser. * * Accepts an `AbortSignal` so an editor can cancel the flow when the user * dismisses the prompt, instead of leaving a poll loop running to expiry. */ export declare function awaitValLoginConfirmation(authorization: ValDeviceAuthorization, options?: { host?: string; /** Defaults to the authorization's own `expiresInSeconds`. */ maxDurationMs?: number; signal?: AbortSignal; /** Wall clock, injectable for tests. */ now?: () => number; }): Promise; /** * Write a completed login to the project's personal access token file. * * @returns the path the token was written to. */ export declare function persistPersonalAccessToken(projectRoot: string, result: ValLoginResult): string;