import { type Check, type DoctorResult, type RunDoctorOptions } from "./doctor.js"; import { ensureTaxSetup, type TaxRegistrationSpec } from "./tax-setup.js"; import { type WorkOSRoleSpec } from "./workos-setup.js"; import type { BillingConfig } from "./types.js"; import type { PlanCatalog } from "./plans.js"; export type SetupStep = Check & { /** What ran. Stable, so a caller can filter or key off it. */ step: "plans" | "meter" | "tax" | "webhook" | "workos"; /** True when this step was skipped because the caller didn't ask for it. */ skipped?: boolean; }; export type SetupResult = { livemode: boolean; steps: SetupStep[]; /** `checkBillingSetup` + `checkPlansConfig`, run afterwards. */ doctor: DoctorResult; /** Present ONLY when this run created the webhook endpoint. Stripe never * returns it again: put it in the environment now or lose it. */ webhookSecret?: string; /** True when nothing errored, in the steps or in the doctor. */ healthy: boolean; }; export interface SetupOptions { /** Your `BillingConfig`. Gives the currency and the tax mode, so neither is * restated here and nothing can disagree with what the app runs on. */ config: BillingConfig; /** Reconcile Stripe products/prices for these plans. Omit to skip. */ plans?: PlanCatalog; /** Absolute URL of your Stripe webhook handler. Omit to skip — correct for a * local machine, which uses `stripe listen` instead (see ./dev). */ webhookUrl?: string; /** Prune other endpoints registered on the same URL. Destructive. */ pruneDuplicateWebhooks?: boolean; /** * Stripe Tax setup, for a deployment whose `config.tax` mode is `"stripe"`. * * Ignored otherwise: an account whose rates this library computes has no head * office or registration to configure, and running this on one would create * registrations it doesn't need and will be charged against. */ stripeTax?: { headOffice: Parameters[0]["headOffice"]; registrations: TaxRegistrationSpec[]; taxCode?: string; }; /** * The seller's OWN tax id, printed on every invoice. * * Art. 226(3) requires it, and for a reverse-charged EU B2B supply the supplier's * intracommunity number is mandatory beside the customer's — from the first euro, even * under a small-business exemption. Independent of `stripeTax`: it is about what the * invoice SAYS, not who calculates. */ accountTaxId?: { type: string; value: string; }; /** Create the usage meter eagerly. Default true. */ meter?: boolean; /** * Provision and audit the WorkOS half. * * PROVISIONED: only the roles YOU name in `roles`. WorkOS ships `admin` and * `member`, so there is no default list — a step that never fires would still read * as one that does something. Whether the `admin` slug is present is checked by the * doctor, which is a different claim. * * NOT provisioned, because v10 exposes no API for either: AuthKit's **redirect * URIs** and its appearance/settings. The SDK's only writable `redirect_uris` * belong to a Connect application, which is a different object. The closing report * prints the exact redirect URI to paste rather than implying it was handled. * * Orgs, memberships and `sk_` keys are not provisioned either — they are created * lazily per customer, which is the behaviour you want. * * Pass `{ oauthProxy: true }` when the app mounts the MCP OAuth proxy, which is * what makes `REFRESH_TOKEN_SECRET` required. */ workos?: boolean | { oauthProxy?: boolean; roles?: WorkOSRoleSpec[]; }; } /** * Provision + verify one Stripe environment. Idempotent; safe on every deploy. * * Which environment is decided by `STRIPE_SECRET_KEY` and nothing else, so the * same call is your test setup and your live setup. */ export declare function setupBilling(opts: SetupOptions): Promise; /** * The report as lines of text, because every consumer would otherwise write this * same loop — and the ONE line that must not be missed (a freshly minted webhook * secret, which Stripe will never show again) deserves to be formatted right once. */ export declare function formatSetupReport(result: SetupResult): string; export interface RunBillingCliOptions extends Omit { /** Required here, unlike on the doctor: `setup` provisions FROM it (currency, * tax mode), so a run without it would provision a guess. */ config: BillingConfig; /** Stripe Tax head office + registrations. Ignored unless `config.tax` mode is * `"stripe"` — see `setupBilling`. */ stripeTax?: SetupOptions["stripeTax"]; /** * The SUPPLIER's own VAT number, printed on every invoice (Art. 226(3)). * * Forwarded to `setupBilling`, and it was not: the option existed there and this is the * only entry point either consuming app calls, so the number could not be provisioned at * all through the documented path — every invoice the account issued was defective and the * doctor could only report it. An unreachable capability is the same false statement a dead * tool makes. */ accountTaxId?: SetupOptions["accountTaxId"]; } /** * `setup` | `doctor` (default) over one options object. * * Flags, the same for both verbs: `--url ` names a different endpoint, * `--no-webhook` says there isn't one. `setup` also takes `--prune`, which deletes * other endpoints registered on the same URL. * * **`doctor` is the default and `setup` must be typed**, because the default has to * be the verb that cannot change anything: a bare `pnpm billing` from a laptop * holding live keys should read the account, never provision it. * * Exits the process itself — call it, do not `await` it at the top level, which does * not survive a CJS transform. */ export declare function runBillingCli(opts: RunBillingCliOptions): Promise; //# sourceMappingURL=setup.d.ts.map