import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
//#region src/client/auth.d.ts
type Logger = {
  debug?(...args: unknown[]): void;
  warn?(...args: unknown[]): void;
  error?(...args: unknown[]): void;
};
/**
 * A pluggable source of bearer tokens. The REST client calls `getToken()` on
 * every request and `invalidate()` on a 401 to force the next call to remint.
 */
type TokenProvider = {
  getToken(): Promise<string>;
  invalidate(): void;
};
type JwtCredentials = {
  /** The Key ID (`kid`) of the App Store Connect API key (10 chars). */
  keyId: string;
  /** The Issuer ID — a UUID from Users and Access → Integrations → Keys. */
  issuerId: string;
  /** The `.p8` private key, PEM-encoded (`-----BEGIN PRIVATE KEY-----`). */
  privateKey: string;
  /**
   * Team-scoped keys (created under a specific role) reject a token that has no
   * `scope`; individual keys reject one that has it. Leave undefined for the
   * common case and only set it if you hit a 401 with `NOT_AUTHORIZED`.
   * Each entry is `"METHOD /v1/path"`, e.g. `"GET /v1/apps"`.
   */
  scope?: string[] | undefined;
};
/**
 * Mint a signed App Store Connect JWT. The API requires ES256 with the raw
 * `r || s` signature form (JOSE / IEEE P1363) — Node's default ECDSA output is
 * ASN.1/DER, which Apple rejects with `401 NOT_AUTHORIZED`, hence `dsaEncoding`.
 */
declare const signJwt: (creds: JwtCredentials, nowSeconds: number, ttlSeconds: number) => string;
type TokenProviderOptions = {
  credentials: JwtCredentials;
  logger?: Logger;
  /**
   * Token lifetime in seconds. Apple caps this at 20 minutes (1200s); default to
   * 19 minutes so a token minted just before a slow request is still valid when
   * it lands.
   */
  ttlSeconds?: number;
  /** Remint this many seconds before expiry. Clamped to half the lifetime. */
  refreshSkewSeconds?: number;
  /** Override `Date.now()` for tests. */
  now?: () => number;
};
/**
 * Caches a locally-signed JWT and remints it shortly before it expires. Unlike
 * an OAuth exchange this needs no network call, so there's no single-flight to
 * coordinate — signing is synchronous and cheap.
 */
declare const createTokenProvider: (opts: TokenProviderOptions) => TokenProvider;
/** Trivial token provider that always returns a fixed string. Useful in tests. */
declare const staticTokenProvider: (token: string) => TokenProvider;
//#endregion
//#region src/client/asc.d.ts
type QueryValue = string | number | boolean | string[] | undefined;
type Query = Record<string, QueryValue>;
type RequestOptions = {
  query?: Query;
  body?: unknown;
};
type AscClientOptions = {
  baseUrl?: string;
  tokenProvider: TokenProvider;
  maxRetries?: number;
  fetch?: typeof fetch;
  logger?: Logger;
  userAgent?: string;
};
/** One leg of an asset upload, as handed back in an `uploadOperations` attribute. */
type UploadOperation = {
  method?: string;
  url?: string;
  length?: number;
  offset?: number;
  requestHeaders?: {
    name?: string;
    value?: string;
  }[];
};
/**
 * Minimal fetch-based client for the App Store Connect API. Paths are absolute
 * (`/v1/apps`). Retries a 401 (reminting the token first) and 429/5xx with
 * exponential backoff honoring `Retry-After`.
 */
declare class AppStoreConnectClient {
  private readonly baseUrl;
  private readonly tokenProvider;
  private readonly maxRetries;
  private readonly fetchImpl;
  private readonly logger;
  private readonly userAgent;
  constructor(opts: AscClientOptions);
  /** Issue a request, returning the raw `Response` after the retry loop. */
  private fetchWithRetry;
  /**
   * Execute the `uploadOperations` Apple hands back when an asset is reserved
   * (a screenshot, app preview, …). These URLs are absolute and pre-signed, so
   * this deliberately skips `baseUrl`, the `Authorization` header and the JSON
   * encoding that `request()` applies — sending a Bearer token to Apple's blob
   * store gets the request rejected.
   *
   * Parts go up sequentially: assets are a few MB and usually a single
   * operation, so parallelism would add failure modes for no real gain. The
   * URLs are short-lived and single-use, so a failure here is not resumable.
   */
  uploadAsset(operations: UploadOperation[], data: Uint8Array): Promise<void>;
  request<T = unknown>(method: string, path: string, opts?: RequestOptions): Promise<T>;
  /**
   * Download a report. `/v1/salesReports` and `/v1/financeReports` answer with a
   * GZIP-compressed TSV body (not JSON), so this gunzips and returns plain text.
   */
  downloadReport(path: string, query: Query): Promise<string>;
  private parseErrors;
  private errorMessage;
  get<T = unknown>(path: string, query?: Query): Promise<T>;
  /**
   * Turn an absolute `links.next` back into a path this client can request.
   * Returns undefined when the link points somewhere else entirely, so a
   * surprising cursor ends pagination rather than sending our JWT off-host.
   */
  private relativize;
  /**
   * GET a collection, following `links.next` until it runs out.
   *
   * Apple caps `limit` at 200, so any app with more locales (or screenshots)
   * than that silently truncates without this. The next links are absolute and
   * already carry the cursor *and* every original param, so `query` is applied
   * to the first page only — re-applying it would clobber the cursor.
   */
  getAll<T = unknown>(path: string, query?: Query, maxPages?: number): Promise<{
    data: T[];
    pages: number;
  }>;
  post<T = unknown>(path: string, body?: unknown, query?: Query): Promise<T>;
  patch<T = unknown>(path: string, body?: unknown, query?: Query): Promise<T>;
  del<T = unknown>(path: string, body?: unknown, query?: Query): Promise<T>;
}
//#endregion
//#region src/config.d.ts
declare const ConfigSchema: z.ZodObject<{
  keyId: z.ZodString;
  issuerId: z.ZodString;
  privateKey: z.ZodString;
  vendorNumber: z.ZodOptional<z.ZodString>;
  allowWrites: z.ZodDefault<z.ZodBoolean>;
  maxRetries: z.ZodDefault<z.ZodNumber>;
  tokenTtlSeconds: z.ZodDefault<z.ZodNumber>;
  metadataRoot: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<string, string>>;
}, z.core.$strict>;
type Config = z.infer<typeof ConfigSchema>;
/**
 * The on-disk config document. Keys are camelCase to mirror `Config` rather than
 * the env var names: this is a typed JSON file, not a shell.
 *
 * `.strict()` on purpose — a typo'd `keyID` must be an error. Silently ignoring
 * an unknown key looks exactly like "that setting had no effect", which is the
 * worst way to learn your credentials came from somewhere else.
 */
declare const FileConfigSchema: z.ZodObject<{
  keyId: z.ZodOptional<z.ZodString>;
  issuerId: z.ZodOptional<z.ZodString>;
  p8: z.ZodOptional<z.ZodString>;
  p8Path: z.ZodOptional<z.ZodString>;
  vendorNumber: z.ZodOptional<z.ZodString>;
  allowWrites: z.ZodOptional<z.ZodBoolean>;
  maxRetries: z.ZodOptional<z.ZodNumber>;
  tokenTtlSeconds: z.ZodOptional<z.ZodNumber>;
  metadataRoot: z.ZodOptional<z.ZodString>;
}, z.core.$strict>;
type FileConfig = z.infer<typeof FileConfigSchema>;
/**
 * Where the config file lives, most specific first: an explicit override, then
 * the XDG location, then the conventional `~/.config`.
 */
declare const resolveConfigPath: (env?: NodeJS.ProcessEnv) => string;
/**
 * Resolve the `.p8` private key from an inline PEM (handy for Docker/CI secrets)
 * or a file path. Exactly one must be set.
 *
 * Whichever source names a key wins outright: an inline PEM in the environment
 * is not a conflict with a `p8Path` in the config file, it simply overrides it.
 * Only naming both *within one source* is a genuine ambiguity.
 */
declare const resolvePrivateKey: (env: NodeJS.ProcessEnv, file?: FileConfig) => string;
/**
 * Environment first, config file second, **per field** — not whole-source.
 * Docker and CI inject the environment and must keep working untouched, while a
 * one-off `APP_STORE_CONNECT_ALLOW_WRITES=0` still has to override a file that
 * says `true`. Merging field by field is the only rule that gives both.
 */
declare const loadConfig: (env?: NodeJS.ProcessEnv, configPath?: string) => Config;
//#endregion
//#region src/server.d.ts
declare const SERVER_NAME: string;
declare const SERVER_VERSION: string;
declare const USER_AGENT: string;
type CreateServerOptions = {
  config: Config;
  fetch?: typeof fetch;
  logger?: Logger;
  /** Override the token provider (tests). */
  tokenProvider?: TokenProvider;
};
type CreatedServer = {
  server: McpServer;
  client: AppStoreConnectClient;
  tokenProvider: TokenProvider;
};
declare const createServer: (opts: CreateServerOptions) => CreatedServer;
//#endregion
//#region src/client/shape.d.ts
type Rec = Record<string, unknown>;
type Resource = {
  type?: unknown;
  id?: unknown;
  attributes?: Rec;
};
/** Flatten one JSON:API resource to `{ id, type, ...attributes }`. */
declare const summarizeResource: (value: unknown) => unknown;
/**
 * Summarize a full list/single response: flatten each resource in `data` and
 * surface `meta` (totals) and `links.next` (the pagination cursor) when present.
 */
declare const summarizeResponse: (response: unknown) => unknown;
//#endregion
//#region src/client/errors.d.ts
/** One entry of App Store Connect's JSON:API `errors` array. */
type AppStoreConnectError = {
  status?: string;
  code?: string;
  title?: string;
  detail?: string;
};
declare class AppStoreConnectApiError extends Error {
  readonly name = "AppStoreConnectApiError";
  readonly status: number;
  readonly errors: AppStoreConnectError[] | unknown;
  constructor(message: string, opts: {
    status: number;
    errors?: AppStoreConnectError[] | unknown;
  });
}
/** Thrown when a write tool is reached while APP_STORE_CONNECT_ALLOW_WRITES is off. */
declare class WritesDisabledError extends Error {
  readonly name = "WritesDisabledError";
  constructor(what: string);
}
//#endregion
//#region src/tools/index.d.ts
type ToolContext = {
  /** Register the mutating tools too. Off by default — see APP_STORE_CONNECT_ALLOW_WRITES. */
  allowWrites: boolean;
  /** Vendor number for sales/finance reports. Reports fail with a clear error when unset. */
  vendorNumber?: string | undefined;
  /**
   * Where this repo keeps its metadata tree, already normalized. Baked into the
   * listing tool descriptions at registration time, which is the only channel
   * that tells the caller where to write the files.
   */
  metadataRoot: string;
};
/**
 * Register the App Store Connect tools. Read tools are always registered; write
 * tools are only registered when `allowWrites` is set, so with the flag off they
 * are not merely refused — they are invisible, and cannot be called at all.
 */
declare const registerTools: (server: McpServer, client: AppStoreConnectClient, ctx: ToolContext) => void;
//#endregion
export { AppStoreConnectApiError, AppStoreConnectClient, type AppStoreConnectError, type AscClientOptions, type Config, type CreateServerOptions, type CreatedServer, type FileConfig, type JwtCredentials, type Logger, type Query, type QueryValue, type Resource, SERVER_NAME, SERVER_VERSION, type TokenProvider, type ToolContext, USER_AGENT, WritesDisabledError, createServer, createTokenProvider, loadConfig, registerTools, resolveConfigPath, resolvePrivateKey, signJwt, staticTokenProvider, summarizeResource, summarizeResponse };
//# sourceMappingURL=index.d.ts.map