import { B as Boundary, P as Project, C as Config } from './variant-BqU-O12A.js'; export { b as CONFIG_FILENAMES, c as CONFIG_VERSION, d as CommandCall, e as CommandResult, f as ConfigError, F as FileSystem, H as HeaderRow, g as HttpRequest, h as HttpResponse, L as LoadOptions, i as Logger, O as OtaConfig, j as ParseResult, R as Reporter, k as ReporterOptions, l as RunOptions, m as RunStart, S as Step, T as TargetConfig, n as ascEntityName, a as assertSingleSegment, o as bundleIdFor, p as configSchema, q as createReporter, r as displayNameFor, s as exceedsLabelBudget, t as findConfigFile, u as formatConfigErrors, v as formatDuration, w as isInteractive, x as jsonSchema, y as labelPrefixFor, z as loadProject, A as nodeBoundary, D as nodeFileSystem, E as nodeReporter, G as noiseWordsFor, I as parseConfig, J as projectFrom, K as sanitizeName, M as sanitizeSuffix, N as silentReporter, Q as variantTitle, U as variantWords } from './variant-BqU-O12A.js'; import { S3ClientConfig, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'; import 'zod'; /** * The failure type, on its own so that everything can throw it. * * It lived in `project.ts`, which meant the boundary — the lowest layer, which * depends on nothing — had to import the layer above it to report a failure. * That cycle left modules half-initialized at runtime and surfaced as a * `ReferenceError` naming an export that plainly exists. */ /** An expected failure that has already explained itself: printed as one line, no stack. */ declare class JetbridgeError extends Error { readonly name = "JetbridgeError"; } /** A function declaration, not an arrow: TypeScript only narrows control flow through one. */ declare function fail(message: string): never; /** * Git, only as far as naming a variant needs it. * * Everything here degrades rather than throws: jetbridge has to work in a * checkout that is not a git repository at all, and in a repository whose * default branch is not the one this tool happens to assume. */ interface GitStamp { sha: string; shortSha: string; /** Tracked files are modified, so the binary would not match the stamped SHA. */ dirty: boolean; } /** The current branch, or empty outside a repository or on a detached HEAD. */ declare function currentBranch(boundary: Boundary, cwd: string): string; declare function onDefaultBranch(boundary: Boundary, project: Project): boolean; /** * What this checkout would build. * * Untracked files are ignored deliberately: they are not in the project file, * so they cannot reach the binary, and a working checkout routinely carries * harmless untracked files. */ declare function gitStamp(boundary: Boundary, cwd: string): GitStamp | null; /** A bare `--suffix` means "name it after the branch I am on". */ declare function branchSuffix(boundary: Boundary, project: Project): string; interface ProvisionedProfile { target: string; bundleId: string; profileName: string; /** Absolute path of the installed `.mobileprovision`. */ installedAt: string; uuid: string; } interface ProvisionOptions { suffix: string; displayName: string; /** `IOS_APP_DEVELOPMENT` for a cabled install, `IOS_APP_ADHOC` for OTA. */ profileType?: string; } /** * Register everything a variant needs and install its profiles. Returns one * entry per target, in configuration order, for the build to sign against. */ declare function provisionVariant(boundary: Boundary, project: Project, options: ProvisionOptions): Promise; interface WiredOptions { /** Stream the full xcodebuild log instead of the quiet one. */ verbose?: boolean; /** Build somewhere other than the per-variant cache. */ derivedData?: string; suffix: string; displayName: string; /** Install to one device: identifier, name, UDID or serial. */ device?: string; configuration?: string; /** Wipe the cached DerivedData first, for a genuinely corrupt build. */ clean?: boolean; /** Bypass the on-disk profile cache — reach for this after a certificate rotation. */ reprovision?: boolean; } declare function wiredInstall(boundary: Boundary, project: Project, options: WiredOptions): Promise; interface SimOptions { /** Stream the full xcodebuild log instead of the quiet one. */ verbose?: boolean; /** Build somewhere other than the per-variant cache. */ derivedData?: string; suffix: string; displayName: string; /** A simulator name or udid. Empty picks a booted-or-available default. */ device?: string; configuration?: string; /** Wipe the cached DerivedData first, for a genuinely corrupt build. */ clean?: boolean; } declare function simInstall(boundary: Boundary, project: Project, options: SimOptions): Promise; /** * The bucket half of an over-the-air install: where an object lands, what URL * the phone fetches it from, and the check that it can. * * Nothing here knows what a build is. It knows keys, bytes and one HEAD * request — which is what lets the whole upload path be tested without a * network, and what keeps the reachability check in one place instead of at * every call site that prints a URL. */ /** The slice of the S3 client this tool uses. A test supplies its own. */ interface S3Like { send(command: PutObjectCommand | GetObjectCommand): Promise<{ Body?: { transformToString(): Promise; }; }>; } type S3Factory = (config: S3ClientConfig) => S3Like; /** * One row per uploaded build, kept in the bucket. It is the source of truth for * the index page, which is why the page can be rebuilt from bucket state alone * without re-archiving anything. */ interface BuildRecord { /** `-`: unique per variant and version, and a key segment. */ buildId: string; appName: string; bundleId: string; version: string; build: string; versionTag: string; variantBadge: string; branch: string; commit: string; dirty: boolean; ipaSizeLabel: string; ipaSizeBytes: number; builtAt: string; /** ISO instant of the upload — the sort key. */ uploadedAt: string; } interface OtaOptions { /** Stream the full xcodebuild log instead of the quiet one. */ verbose?: boolean; /** Build somewhere other than the per-variant cache. */ derivedData?: string; suffix: string; displayName: string; configuration?: string; gitSha?: string; /** Injected by tests. Production uses the AWS SDK client. */ s3?: S3Factory; } interface OtaResult { installUrl: string; indexUrl: string; manifestUrl: string; record: BuildRecord; builds: number; } declare function otaInstall(boundary: Boundary, project: Project, options: OtaOptions): Promise; /** * Rebuild the index page from the bucket alone — no build, no archive. For when * the page was clobbered, the registry was hand-edited, or the branding * changed and every page should say the new thing. */ declare function reindex(boundary: Boundary, project: Project, options?: { s3?: S3Factory; }): Promise<{ indexUrl: string; builds: number; }>; /** * What this project has registered with Apple, and how to get rid of it. * * Every `--suffix` install mints permanent account state: a bundle id, one more * for each extension, and a provisioning profile apiece. Nothing ever removed * them, so they accrue — one set per branch anyone ever tested, plus one per * typo. * * DELETION IS IRREVERSIBLE AND APPLE RESTORES NOTHING, so a dry run is the * DEFAULT everywhere: the plan is printed, nothing is sent, and the command * succeeds. `yes` executes. Nothing here ever prompts — an agent or a piped * session has no terminal to answer with, and the absence of `yes` is already * an unambiguous answer. * * The base bundle id is protected twice over: `groupVariants` never classifies * it as a variant, and `assertDeletable` checks again immediately before every * DELETE. Losing it breaks signing for every build this project ever makes. */ interface RegisteredBundleId { id: string; identifier: string; name: string; } interface RegisteredProfile { id: string; name: string; /** ISO 8601, as Apple returns it. Empty when the account did not say. */ createdDate: string; } /** One variant and everything the account holds for it. */ interface RegisteredVariant { suffix: string; app: RegisteredBundleId; extensions: RegisteredBundleId[]; profiles: RegisteredProfile[]; } interface VariantRecord { slug: string; bundleId: string; name: string; extensions: string[]; profileCount: number; /** `YYYY-MM-DD` of the earliest profile, or null when none is left. */ created: string | null; } /** * The listing. * * The payload goes to STDOUT — every human line is stderr, and `bundles ls * --json | jq` has to receive something. With `--json` that payload is the whole * of stdout: one array, not an event stream, because scripts already parse it * that way. It is also returned, so the shape is testable without scraping a * stream. */ declare function listBundles(boundary: Boundary, project: Project, options?: { json?: boolean; }): Promise; interface RemovalResult { /** Slugs that were, or would have been, removed. */ slugs: string[]; /** True when nothing was sent — the default. */ dryRun: boolean; } declare function removeBundles(boundary: Boundary, project: Project, options: { suffixes: string[]; yes?: boolean; }): Promise; declare function pruneBundles(boundary: Boundary, project: Project, options?: { yes?: boolean; }): Promise; /** * Register a variant and mint its profiles without building anything. * * The only route to a refresh after a certificate rotation or a newly registered * phone that does not also cost a full build. */ declare function provisionBundles(boundary: Boundary, project: Project, options: { suffix: string; displayName: string; }): Promise; /** A detected value and the file that produced it. */ interface Suggestion { value: T; /** Path relative to the project root, for a message a human can check. */ source: string; } interface DetectedTarget { name: string; productType?: string; isApp: boolean; bundleId?: string; /** One bundle-id segment for an extension; unset for the app itself. */ bundleIdSuffix?: string; entitlements?: Suggestion; /** A reduced entitlements file found beside the shipping one. */ variantEntitlements?: Suggestion; } interface Detection { root: string; iosDir: Suggestion; xcodeproj?: Suggestion; xcworkspace?: Suggestion; projectYml?: Suggestion; configurations?: Suggestion; schemes: string[]; scheme?: Suggestion; teamId?: Suggestion; baseBundleId?: Suggestion; displayName?: Suggestion; targets: DetectedTarget[]; /** Everything the wizard should say out loud before it starts asking. */ warnings: string[]; } interface DetectOptions { /** Where the config file will live. Every suggested path is relative to it. */ root: string; /** Skip the search and read this directory, relative to `root`. */ iosDir?: string; } declare function detectProject(boundary: Boundary, options: DetectOptions): Detection; interface Question { /** Stable key: the scripted answer's name, and what a missing answer reports. */ name: string; message: string; /** Where a suggested value came from, shown next to the default. */ hint?: string; } interface TextQuestion extends Question { initial?: string; /** Returns a message when the answer is unusable, `undefined` when it is fine. */ validate?: (value: string) => string | undefined; } interface ConfirmQuestion extends Question { initial?: boolean; } interface SelectQuestion extends Question { options: Array<{ value: T; label?: string; hint?: string; }>; initial?: T; } interface Prompter { text(question: TextQuestion): Promise; confirm(question: ConfirmQuestion): Promise; select(question: SelectQuestion): Promise; /** A block of text, not a question. */ note(message: string, title?: string): void; } interface Drift { /** Dotted config path, e.g. `project.scheme`. */ path: string; current: unknown; detected: unknown; /** Why the current value is suspect, when it is more than "they differ". */ note?: string; source: string; } interface OtaStorageInput { bucket: string; region: string; endpoint?: string; publicBaseUrl: string; prefix: string; } interface OtaRoundTripResult { ok: boolean; /** One line, shown either way: what was proved, or what broke. */ detail: string; } /** * Upload a small object, fetch it back over the public base URL, delete it. * Injected: a wrong bucket policy is worth ten seconds here instead of a * fifteen-minute archive that cannot be installed. */ type OtaRoundTrip = (boundary: Boundary, storage: OtaStorageInput) => Promise; interface InitOptions { /** Where the config file goes. Defaults to the working directory. */ cwd?: string; /** Accept every detected default and never prompt. */ yes?: boolean; iosDir?: string; xcodeproj?: string; xcworkspace?: string; scheme?: string; teamId?: string; bundleId?: string; displayName?: string; configurations?: string[]; wired?: string; sim?: string; archive?: string; ascKeyIdEnv?: string; ascIssuerIdEnv?: string; ota?: boolean; otaBucket?: string; otaRegion?: string; otaEndpoint?: string; otaPublicBaseUrl?: string; /** `path` or `none`; validated here so a typo cannot reach the config. */ otaAccess?: string; } interface InitDeps { prompts: Prompter; otaRoundTrip?: OtaRoundTrip; } interface InitResult { status: 'written' | 'declined' | 'unchanged'; configPath: string; config?: Config; /** What a repair pass found, empty on a first run. */ drift: Drift[]; } declare function runInit(boundary: Boundary, options: InitOptions, deps: InitDeps): Promise; export { Boundary, Config, type Detection, type GitStamp, type InitOptions, type InitResult, JetbridgeError, type OtaOptions, type OtaResult, Project, type ProvisionOptions, type ProvisionedProfile, type RegisteredVariant, type RemovalResult, type SimOptions, type VariantRecord, type WiredOptions, branchSuffix, currentBranch, detectProject, fail, gitStamp, listBundles, onDefaultBranch, otaInstall, provisionBundles, provisionVariant, pruneBundles, reindex, removeBundles, runInit, simInstall, wiredInstall };