@capgo/cli 7.122.6 → 7.122.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +545 -545
- package/dist/package.json +5 -3
- package/dist/src/build/onboarding/apple-api.d.ts +62 -0
- package/dist/src/build/onboarding/bundle-id-detector.d.ts +74 -0
- package/dist/src/build/onboarding/file-picker.d.ts +10 -0
- package/dist/src/build/onboarding/macos-signing.d.ts +31 -0
- package/dist/src/build/onboarding/types.d.ts +63 -1
- package/dist/src/build/onboarding/ui/app.d.ts +18 -0
- package/dist/src/build/onboarding/ui/components.d.ts +62 -0
- package/dist/src/build/onboarding/ui/shell.d.ts +9 -0
- package/dist/src/build/onboarding/ui/steps/ios-import.d.ts +33 -1
- package/dist/src/sdk.js +1 -1
- package/package.json +5 -3
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.122.
|
|
4
|
+
"version": "7.122.7",
|
|
5
5
|
"description": "A CLI to upload to capgo servers",
|
|
6
6
|
"author": "Martin martin@capgo.app",
|
|
7
7
|
"license": "Apache 2.0",
|
|
@@ -105,8 +105,9 @@
|
|
|
105
105
|
"test:payload-split": "bun test/test-payload-split.mjs",
|
|
106
106
|
"test:macos-signing": "bun test/test-macos-signing.mjs",
|
|
107
107
|
"test:apple-api-import-helpers": "bun test/test-apple-api-import-helpers.mjs",
|
|
108
|
+
"test:bundle-id-detector": "bun test/test-bundle-id-detector.mjs",
|
|
108
109
|
"test:manifest-path-encoding": "bun test/test-manifest-path-encoding.mjs",
|
|
109
|
-
"test": "bun run build && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:mcp-analytics && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:apple-api-import-helpers && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-render-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit",
|
|
110
|
+
"test": "bun run build && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:mcp-analytics && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:apple-api-import-helpers && bun run test:bundle-id-detector && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-render-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit",
|
|
110
111
|
"test:build-platform-selection": "bun test/test-build-platform-selection.mjs",
|
|
111
112
|
"test:ai-log-capture": "bun test/test-ai-log-capture.mjs",
|
|
112
113
|
"test:ai-analyze-flow": "bun test/test-ai-analyze-flow.mjs",
|
|
@@ -130,7 +131,8 @@
|
|
|
130
131
|
"jsonwebtoken": "^9.0.3",
|
|
131
132
|
"node-forge": "^1.4.0",
|
|
132
133
|
"qrcode": "^1.5.4",
|
|
133
|
-
"react": "^19.2.6"
|
|
134
|
+
"react": "^19.2.6",
|
|
135
|
+
"string-width": "^8.2.1"
|
|
134
136
|
},
|
|
135
137
|
"devDependencies": {
|
|
136
138
|
"@antfu/eslint-config": "^9.0.0",
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Uses ES256 algorithm with the .p8 private key.
|
|
4
4
|
*/
|
|
5
5
|
export declare function generateJwt(keyId: string, issuerId: string, p8Content: string): string;
|
|
6
|
+
export declare class AppleApiHttpError extends Error {
|
|
7
|
+
readonly status: number;
|
|
8
|
+
constructor(status: number, message: string);
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
11
|
* Verify the API key works and try to detect the team ID from existing certificates.
|
|
8
12
|
* Throws on 401/403 with a user-friendly message.
|
|
@@ -23,6 +27,50 @@ export interface AscDistributionCert {
|
|
|
23
27
|
*/
|
|
24
28
|
certificateContent?: string;
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Why a local Keychain cert can't be used to ship builds.
|
|
32
|
+
*
|
|
33
|
+
* Concrete enumeration so the import-pick-identity UI can render a stable
|
|
34
|
+
* Reason column and so we can add specific guidance per reason (e.g.
|
|
35
|
+
* "managed" certs get a "can't sign locally" note, "not-visible" certs get
|
|
36
|
+
* a "Open Developer Portal to verify" note).
|
|
37
|
+
*/
|
|
38
|
+
export type CertAvailabilityReason = 'expired' | 'managed' | 'not-visible' | 'check-failed' | 'no-private-key';
|
|
39
|
+
export interface CertAvailability {
|
|
40
|
+
available: boolean;
|
|
41
|
+
reason?: CertAvailabilityReason;
|
|
42
|
+
/** Short human-readable reason for display in the picker. */
|
|
43
|
+
reasonText?: string;
|
|
44
|
+
/** When available — Apple-side cert resource id for downstream API calls. */
|
|
45
|
+
appleCertId?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Pure classifier: given a local cert + the result of an Apple-side lookup,
|
|
49
|
+
* decide whether it's usable for shipping builds and surface a short
|
|
50
|
+
* reasonText for the picker UI.
|
|
51
|
+
*
|
|
52
|
+
* Exported separately from the lookup function so we can unit-test the
|
|
53
|
+
* decision logic without mocking network calls. Callers compose:
|
|
54
|
+
*
|
|
55
|
+
* const certId = await findCertIdBySha1(token, identity.sha1)
|
|
56
|
+
* .catch(err => { lookupError = err; return null })
|
|
57
|
+
* const availability = classifyCertAvailability({
|
|
58
|
+
* localExpirationDate: identity.expirationDate,
|
|
59
|
+
* appleCertId: certId,
|
|
60
|
+
* lookupError,
|
|
61
|
+
* })
|
|
62
|
+
*
|
|
63
|
+
* The `expired` and `managed` branches don't need a lookup — they're checked
|
|
64
|
+
* up-front from local metadata. Callers can pass null `appleCertId` without
|
|
65
|
+
* having run the lookup at all when those local-side conditions already
|
|
66
|
+
* disqualify the identity.
|
|
67
|
+
*/
|
|
68
|
+
export declare function classifyCertAvailability(args: {
|
|
69
|
+
localExpirationDate?: string;
|
|
70
|
+
isManaged?: boolean;
|
|
71
|
+
appleCertId: string | null;
|
|
72
|
+
lookupError?: unknown;
|
|
73
|
+
}): CertAvailability;
|
|
26
74
|
/**
|
|
27
75
|
* List all iOS distribution certificates.
|
|
28
76
|
*
|
|
@@ -51,6 +99,20 @@ export declare function computeCertSha1(certificateContentBase64: string): strin
|
|
|
51
99
|
* creation. Returns null if no Apple-side cert matches the SHA1.
|
|
52
100
|
*/
|
|
53
101
|
export declare function findCertIdBySha1(token: string, sha1: string): Promise<string | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Like {@link findCertIdBySha1} but returns the full Apple-side cert
|
|
104
|
+
* record (id + name + expirationDate + serialNumber) when matched. Used
|
|
105
|
+
* by the eager batch validation so the picker / manual-portal-walkthrough
|
|
106
|
+
* step can surface concrete disambiguators (expiration date, last few
|
|
107
|
+
* chars of serial number — both visible in the Apple Developer Portal
|
|
108
|
+
* when the user clicks into a cert) that help the user pick the right
|
|
109
|
+
* row when multiple distribution certs are listed for the same team.
|
|
110
|
+
*
|
|
111
|
+
* Apple's API does NOT expose a "created by" field on certs (the portal
|
|
112
|
+
* UI shows it, but `/v1/certificates` doesn't return that column). The
|
|
113
|
+
* disambiguators we can give are expirationDate + serialNumber.
|
|
114
|
+
*/
|
|
115
|
+
export declare function findCertBySha1(token: string, sha1: string): Promise<AscDistributionCert | null>;
|
|
54
116
|
/**
|
|
55
117
|
* List all provisioning profiles linked to a specific Apple-side certificate.
|
|
56
118
|
* Used by the import-flow no-match-recovery menu to surface profiles that
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type BundleIdSource = 'pbxproj-release' | 'pbxproj-fallback' | 'plist' | 'capacitor-config';
|
|
2
|
+
export interface BundleIdCandidate {
|
|
3
|
+
value: string;
|
|
4
|
+
source: BundleIdSource;
|
|
5
|
+
/** Short human-readable label for the picker, e.g. "project.pbxproj (Release)". */
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DetectedBundleIds {
|
|
9
|
+
/** PRODUCT_BUNDLE_IDENTIFIER from project.pbxproj, preferring Release config. */
|
|
10
|
+
pbxproj: BundleIdCandidate | null;
|
|
11
|
+
/**
|
|
12
|
+
* Info.plist CFBundleIdentifier when it's a literal value (not the common
|
|
13
|
+
* `$(PRODUCT_BUNDLE_IDENTIFIER)` placeholder, which we drop because it
|
|
14
|
+
* adds nothing the pbxproj source doesn't already cover).
|
|
15
|
+
*/
|
|
16
|
+
plist: BundleIdCandidate | null;
|
|
17
|
+
/** capacitor.config.ts/json's appId — always present (it's a required arg). */
|
|
18
|
+
capacitor: BundleIdCandidate;
|
|
19
|
+
/**
|
|
20
|
+
* The best-guess Apple-side bundle ID, picked in priority order:
|
|
21
|
+
* pbxproj-release > pbxproj-fallback > plist > capacitor. Returned for
|
|
22
|
+
* convenience so callers don't have to re-implement the precedence.
|
|
23
|
+
*/
|
|
24
|
+
recommended: BundleIdCandidate;
|
|
25
|
+
/**
|
|
26
|
+
* True when the recommended value differs from capacitor.config.appId.
|
|
27
|
+
* Used by the confirm-app-id step to decide whether to surface a question
|
|
28
|
+
* at all — when they match, nothing's worth asking about.
|
|
29
|
+
*/
|
|
30
|
+
mismatch: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Deduplicated, ordered list of candidates ready to render as Select
|
|
33
|
+
* options. Empty list is impossible (capacitor is always included).
|
|
34
|
+
*/
|
|
35
|
+
candidates: BundleIdCandidate[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parse `PRODUCT_BUNDLE_IDENTIFIER = "..."` lines from pbxproj content.
|
|
39
|
+
* Returns the Release-config value if present, else the first non-Release
|
|
40
|
+
* value. Returns null when no bundle id can be extracted.
|
|
41
|
+
*
|
|
42
|
+
* Looks like a re-implementation of pbxproj-parser.ts's resolveBundleId, but
|
|
43
|
+
* that one needs an XCConfigurationList id (it walks from a target). This
|
|
44
|
+
* one needs to work standalone given only the file contents — so it
|
|
45
|
+
* collects all PRODUCT_BUNDLE_IDENTIFIER values, groups by adjacent
|
|
46
|
+
* `name = Release`/`name = Debug` markers, and prefers Release. Less
|
|
47
|
+
* accurate for multi-target projects but good enough for the "what should
|
|
48
|
+
* we pre-fill" use case here.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parsePbxprojBundleId(pbxprojContent: string): BundleIdCandidate | null;
|
|
51
|
+
/**
|
|
52
|
+
* Parse Info.plist's CFBundleIdentifier from raw XML.
|
|
53
|
+
* Returns null when the file is empty, when CFBundleIdentifier is absent,
|
|
54
|
+
* or when it's a `$(PRODUCT_BUNDLE_IDENTIFIER)` variable reference (we drop
|
|
55
|
+
* the placeholder so the picker doesn't list a non-actionable option).
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseInfoPlistBundleId(plistContent: string): BundleIdCandidate | null;
|
|
58
|
+
/**
|
|
59
|
+
* Read project.pbxproj and Info.plist from the iOS dir and return all
|
|
60
|
+
* available bundle id candidates, plus the recommended one and a
|
|
61
|
+
* mismatch flag.
|
|
62
|
+
*
|
|
63
|
+
* Filesystem reads are best-effort — when either file is missing or
|
|
64
|
+
* unreadable, we silently skip that source. The capacitor candidate is
|
|
65
|
+
* always present.
|
|
66
|
+
*/
|
|
67
|
+
export declare function detectIosBundleIds(opts: {
|
|
68
|
+
/** Project root (typically `process.cwd()`). */
|
|
69
|
+
cwd: string;
|
|
70
|
+
/** Subdirectory under cwd holding the iOS project (typically "ios"). */
|
|
71
|
+
iosDir: string;
|
|
72
|
+
/** Bundle id read from capacitor.config.ts/json — always known. */
|
|
73
|
+
capacitorAppId: string;
|
|
74
|
+
}): DetectedBundleIds;
|
|
@@ -25,6 +25,16 @@ export declare function openSaveFilePicker(opts: SaveFilePickerOptions): Promise
|
|
|
25
25
|
* Accepts .jks, .keystore, and .p12 extensions.
|
|
26
26
|
*/
|
|
27
27
|
export declare function openKeystorePicker(): Promise<string | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Open the macOS native file picker filtered to .mobileprovision files.
|
|
30
|
+
* Returns the selected path, or null if the user cancelled.
|
|
31
|
+
*
|
|
32
|
+
* Used by the no-match-recovery "Use a .mobileprovision file from disk"
|
|
33
|
+
* option — covers users who have a profile downloaded somewhere outside
|
|
34
|
+
* Xcode's standard provisioning-profile directories (e.g. a downloads
|
|
35
|
+
* folder, an artifact from another machine, a shared team archive).
|
|
36
|
+
*/
|
|
37
|
+
export declare function openMobileprovisionPicker(): Promise<string | null>;
|
|
28
38
|
/**
|
|
29
39
|
* Open the macOS native file picker filtered to Google Play service account
|
|
30
40
|
* JSON files. Used by the Android onboarding "import existing SA" path.
|
|
@@ -86,6 +86,37 @@ export declare function scanProvisioningProfiles(homeDirOverride?: string): Prom
|
|
|
86
86
|
* Pure function — no I/O.
|
|
87
87
|
*/
|
|
88
88
|
export declare function matchIdentitiesToProfiles(identities: readonly SigningIdentity[], profiles: readonly DiscoveredProfile[]): IdentityProfileMatch[];
|
|
89
|
+
/**
|
|
90
|
+
* Compare a provisioning profile's bundle id against the app's concrete bundle
|
|
91
|
+
* id, honoring Apple's wildcard syntax. The mobileprovision parser leaves the
|
|
92
|
+
* asterisk in place after stripping the team-id prefix, so a wildcard profile
|
|
93
|
+
* arrives here as either the bare `*` (matches everything the team owns) or a
|
|
94
|
+
* suffix wildcard like `com.example.*` (matches `com.example.<anything>`).
|
|
95
|
+
*
|
|
96
|
+
* Exported so the file-picker validation in the Ink UI can reuse the same
|
|
97
|
+
* matching rule as `filterProfilesForApp` — otherwise a wildcard
|
|
98
|
+
* `.mobileprovision` picked manually would be hard-rejected even though the
|
|
99
|
+
* underlying profile is valid for the current app.
|
|
100
|
+
*/
|
|
101
|
+
export declare function bundleIdMatches(profileBundleId: string, appId: string): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Filter profiles that are actually usable for a given Capacitor app + iOS
|
|
104
|
+
* distribution mode. Used by the import-existing flow to detect dead-end
|
|
105
|
+
* situations where an identity has profiles for a different app or the wrong
|
|
106
|
+
* distribution mode — in which case the no-match-recovery menu can offer
|
|
107
|
+
* "fetch / create via Apple" instead of dropping the user at an empty picker.
|
|
108
|
+
*
|
|
109
|
+
* `importDistribution` is null/undefined when the user hasn't picked yet —
|
|
110
|
+
* in that case any profileType is accepted.
|
|
111
|
+
*
|
|
112
|
+
* Bundle-id comparison goes through {@link bundleIdMatches} so wildcard
|
|
113
|
+
* profiles (the norm for ad_hoc/enterprise teams that share one profile
|
|
114
|
+
* across many apps) are accepted alongside literal-equality matches. Apple
|
|
115
|
+
* never issues wildcard `app_store` profiles in practice, so when the caller
|
|
116
|
+
* pins `importDistribution = 'app_store'` the conjunction naturally drops
|
|
117
|
+
* any ad_hoc/enterprise wildcards that happen to be installed.
|
|
118
|
+
*/
|
|
119
|
+
export declare function filterProfilesForApp(profiles: readonly DiscoveredProfile[], appId: string, importDistribution: 'app_store' | 'ad_hoc' | null | undefined): DiscoveredProfile[];
|
|
89
120
|
/**
|
|
90
121
|
* Generate a cryptographically random passphrase suitable for wrapping the
|
|
91
122
|
* exported PKCS#12. 32 bytes of entropy → 64-char hex string.
|
|
@@ -16,12 +16,52 @@ export interface OnboardingResult {
|
|
|
16
16
|
/** Present only when outcome === 'completed'. */
|
|
17
17
|
summary?: OnboardingCompletionSummary;
|
|
18
18
|
}
|
|
19
|
-
export type OnboardingStep = 'welcome' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | 'import-scanning' | 'import-distribution-mode' | 'import-pick-identity' | 'import-pick-profile' | 'import-no-match-recovery' | 'import-
|
|
19
|
+
export type OnboardingStep = 'welcome' | 'resume-prompt' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | 'confirm-app-id' | 'import-scanning' | 'import-distribution-mode' | 'import-pick-identity' | 'import-pick-profile' | 'import-validating-all-certs' | 'import-checking-apple-cert' | 'import-no-match-recovery' | 'import-portal-explanation' | 'import-provide-profile-path' | 'import-create-profile-only' | 'import-export-warning' | 'import-compiling-helper' | 'import-exporting' | 'api-key-instructions' | 'p8-method-select' | 'input-p8-path' | 'input-key-id' | 'input-issuer-id' | 'verifying-key' | 'creating-certificate' | 'cert-limit-prompt' | 'revoking-certificate' | 'creating-profile' | 'duplicate-profile-prompt' | 'deleting-duplicate-profiles' | 'saving-credentials' | 'detecting-ci-secrets' | 'ci-secrets-setup' | 'ci-secrets-target-select' | 'ask-ci-secrets' | 'checking-ci-secrets' | 'confirm-ci-secret-overwrite' | 'uploading-ci-secrets' | 'ci-secrets-failed' | 'ask-github-actions-setup' | 'confirm-secrets-push' | 'ask-export-env' | 'exporting-env' | 'confirm-env-export-overwrite' | 'overwrite-and-export-env' | 'pick-package-manager' | 'pick-build-script' | 'pick-build-script-custom' | 'preview-workflow-file' | 'view-workflow-diff' | 'writing-workflow-file' | 'ask-build' | 'requesting-build' | 'ai-analysis-prompt' | 'ai-analysis-running' | 'ai-analysis-result' | 'ai-analysis-result-scroll' | 'build-complete' | 'no-platform' | 'error';
|
|
20
20
|
export type OnboardingErrorCategory = 'apple_api_unauthorized' | 'apple_api_rate_limited' | 'cert_limit_reached' | 'profile_creation_failed' | 'p8_invalid' | 'keychain_no_identities' | 'keychain_export_failed' | 'keychain_helper_compile_failed' | 'profile_no_match' | 'profile_read_failed' | 'unknown';
|
|
21
21
|
export interface ApiKeyData {
|
|
22
22
|
keyId: string;
|
|
23
23
|
issuerId: string;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Per-identity result of the eager Apple-side validation run. Populated by
|
|
27
|
+
* the `import-validating-all-certs` step useEffect, consumed by the two-
|
|
28
|
+
* table picker in `import-pick-identity`. Kept here (alongside the Step
|
|
29
|
+
* type) so the renderer and the validation logic share a single shape.
|
|
30
|
+
*/
|
|
31
|
+
export interface EnrichedIdentityAvailability {
|
|
32
|
+
/** True when Apple's API returned a SHA1 match for this identity. */
|
|
33
|
+
available: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Stable reason code for unavailable identities. Drives the per-reason
|
|
36
|
+
* detail rendering in the unavailable table (e.g. notice about the
|
|
37
|
+
* Apple-managed signing constraint, or about private-key-missing).
|
|
38
|
+
*/
|
|
39
|
+
reason?: 'expired' | 'managed' | 'not-visible' | 'check-failed' | 'no-private-key';
|
|
40
|
+
/** One-line summary shown in the Reason column of the unavailable table. */
|
|
41
|
+
reasonText?: string;
|
|
42
|
+
/** When available — Apple-side cert resource id, reused downstream. */
|
|
43
|
+
appleCertId?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Apple-side cert name as returned by /v1/certificates. Useful when
|
|
46
|
+
* the local Keychain name differs from the portal name (e.g. multiple
|
|
47
|
+
* "iOS Distribution" certs in the same team — the portal column says
|
|
48
|
+
* exactly which one).
|
|
49
|
+
*/
|
|
50
|
+
appleCertName?: string;
|
|
51
|
+
/**
|
|
52
|
+
* ISO timestamp from Apple's expiration field. Shown in the manual-
|
|
53
|
+
* portal walkthrough so the user can tell which row to click when
|
|
54
|
+
* multiple certs are listed.
|
|
55
|
+
*/
|
|
56
|
+
appleCertExpirationDate?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Full serial number from Apple. The portal shows it in the cert
|
|
59
|
+
* detail view; surfacing the last 8 chars here gives the user a
|
|
60
|
+
* concrete disambiguator without leaking the full 40-byte serial
|
|
61
|
+
* into the terminal.
|
|
62
|
+
*/
|
|
63
|
+
appleCertSerialNumber?: string;
|
|
64
|
+
}
|
|
25
65
|
export interface CertificateData {
|
|
26
66
|
certificateId: string;
|
|
27
67
|
expirationDate: string;
|
|
@@ -64,6 +104,28 @@ export interface OnboardingProgress {
|
|
|
64
104
|
* Only meaningful when `setupMethod === 'import-existing'`.
|
|
65
105
|
*/
|
|
66
106
|
importDistribution?: 'app_store' | 'ad_hoc';
|
|
107
|
+
/**
|
|
108
|
+
* When set, the user explicitly confirmed an iOS bundle id different from
|
|
109
|
+
* `capacitor.config.appId`. Used for Apple-side operations (cert lookup,
|
|
110
|
+
* profile filtering, `ensureBundleId`, `createProfile`) and as the key in
|
|
111
|
+
* the provisioning_map. The progress-file key and Capgo SaaS API calls
|
|
112
|
+
* still use `appId` so existing build commands continue to find these
|
|
113
|
+
* credentials without forcing the user to edit `capacitor.config`.
|
|
114
|
+
*
|
|
115
|
+
* Persisted so the confirm-app-id step doesn't re-ask on resume — once
|
|
116
|
+
* confirmed, the override sticks unless the configuration context (see
|
|
117
|
+
* `iosBundleIdContextAppId`) changes between CLI runs.
|
|
118
|
+
*/
|
|
119
|
+
iosBundleIdOverride?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Snapshot of `config.appId` at the time the user confirmed the
|
|
122
|
+
* `iosBundleIdOverride`. On the next run we compare this to the current
|
|
123
|
+
* `config.appId`; if it changed (user renamed the app, added/removed a
|
|
124
|
+
* dev-tunnel suffix, etc.) the saved override is stale and we re-ask
|
|
125
|
+
* via the confirm-app-id step. Without this we'd silently keep using a
|
|
126
|
+
* bundle id the user already moved on from.
|
|
127
|
+
*/
|
|
128
|
+
iosBundleIdContextAppId?: string;
|
|
67
129
|
completedSteps: {
|
|
68
130
|
apiKeyVerified?: ApiKeyData;
|
|
69
131
|
certificateCreated?: CertificateData;
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
2
|
import type { OnboardingProgress, OnboardingResult } from '../types.js';
|
|
3
3
|
interface AppProps {
|
|
4
|
+
/**
|
|
5
|
+
* Capgo lookup key (progress files, saved credentials, Capgo SaaS build
|
|
6
|
+
* API). Resolved by `getAppId()`, which prefers
|
|
7
|
+
* `config.plugins.CapacitorUpdater.appId` over `config.appId` so dev-tunnel
|
|
8
|
+
* sandboxes can override the Capgo-side identifier without renaming the
|
|
9
|
+
* iOS bundle. Do NOT use for Apple-side operations — see
|
|
10
|
+
* `iosBundleIdInitial`.
|
|
11
|
+
*/
|
|
4
12
|
appId: string;
|
|
13
|
+
/**
|
|
14
|
+
* Default value for the iOS bundle ID used for Apple-side operations
|
|
15
|
+
* (cert lookup, profile filtering, ensureBundleId, createProfile, and the
|
|
16
|
+
* provisioning_map key). Sourced from `config.appId` directly — what
|
|
17
|
+
* `cap sync` writes into project.pbxproj's PRODUCT_BUNDLE_IDENTIFIER.
|
|
18
|
+
* The user can override at the `confirm-app-id` step when pbxproj and
|
|
19
|
+
* config.appId disagree. command.ts falls back to `appId` if config.appId
|
|
20
|
+
* is missing, so this prop is always a valid string.
|
|
21
|
+
*/
|
|
22
|
+
iosBundleIdInitial: string;
|
|
5
23
|
initialProgress: OnboardingProgress | null;
|
|
6
24
|
/** Resolved iOS directory from capacitor.config (defaults to 'ios') */
|
|
7
25
|
iosDir: string;
|
|
@@ -6,6 +6,36 @@ export declare const Divider: FC<{
|
|
|
6
6
|
export declare const BOX_HEADER_ROWS = 5;
|
|
7
7
|
export declare const COMPACT_HEADER_ROWS = 1;
|
|
8
8
|
export declare const WIZARD_PADDING_ROWS = 2;
|
|
9
|
+
/**
|
|
10
|
+
* Minimal in-house Table component. Auto-sizes each column to the widest
|
|
11
|
+
* value (header or any row cell) up to `maxColumnWidth`, truncates with
|
|
12
|
+
* an ellipsis when a cell exceeds that width, and renders box-drawing
|
|
13
|
+
* borders.
|
|
14
|
+
*
|
|
15
|
+
* Why inline instead of `ink-table`: the published `ink-table@3.1.0` is
|
|
16
|
+
* CommonJS and modern `ink` (v5+) is ESM with top-level await, so bundling
|
|
17
|
+
* fails. This component is the small subset of ink-table's API we need
|
|
18
|
+
* (rows of plain string cells) without the compat headache.
|
|
19
|
+
*
|
|
20
|
+
* The `data` rows must share a single key order so columns line up — we
|
|
21
|
+
* derive the column list from the first row's keys.
|
|
22
|
+
*
|
|
23
|
+
* `cellColor` runs per-cell and returns an Ink color name (or undefined
|
|
24
|
+
* for default). Used by the available/unavailable-certs tables to colour
|
|
25
|
+
* the status column green/red while keeping Name/Team dim.
|
|
26
|
+
*/
|
|
27
|
+
export interface TableProps {
|
|
28
|
+
data: Record<string, string>[];
|
|
29
|
+
/** Hard cap on column width before truncation. Default 50. */
|
|
30
|
+
maxColumnWidth?: number;
|
|
31
|
+
/** Optional per-cell color function. */
|
|
32
|
+
cellColor?: (column: string, value: string, rowIndex: number) => string | undefined;
|
|
33
|
+
/** Optional per-cell dim flag (defaults to false). */
|
|
34
|
+
cellDim?: (column: string, value: string, rowIndex: number) => boolean;
|
|
35
|
+
/** Padding inside each cell (left/right). Default 1. */
|
|
36
|
+
cellPadding?: number;
|
|
37
|
+
}
|
|
38
|
+
export declare const Table: FC<TableProps>;
|
|
9
39
|
export declare const SpinnerLine: FC<{
|
|
10
40
|
text: string;
|
|
11
41
|
}>;
|
|
@@ -29,8 +59,40 @@ export declare const AiResultBanner: FC<{
|
|
|
29
59
|
*/
|
|
30
60
|
export declare const FilteredTextInput: FC<{
|
|
31
61
|
placeholder?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Blacklist of characters to strip from input. Each char in this string is
|
|
64
|
+
* removed from the buffer after every keystroke. Used for casual filtering
|
|
65
|
+
* (e.g. stripping `=` from env-var values).
|
|
66
|
+
*/
|
|
32
67
|
filter?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Whitelist regex matched per-character. Anything not matching is dropped.
|
|
70
|
+
* Takes precedence over `filter` when both are set. Used when the field has
|
|
71
|
+
* a tight format (Apple Key ID is exactly 10 alphanumeric chars; Issuer ID
|
|
72
|
+
* is a UUID; etc.) so users can't even type invalid characters.
|
|
73
|
+
*/
|
|
74
|
+
allowedPattern?: RegExp;
|
|
75
|
+
/**
|
|
76
|
+
* Hard cap on input length. Extra characters past the cap are dropped
|
|
77
|
+
* silently (paste-safe). Pair with `allowedPattern` for known-format fields
|
|
78
|
+
* — e.g. Apple Key ID has `maxLength=10` so a paste of "Key ID: KDTXMK292V"
|
|
79
|
+
* truncates to the first 10 valid chars after filtering.
|
|
80
|
+
*/
|
|
81
|
+
maxLength?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Post-filter transform applied to the entire buffer after each keystroke.
|
|
84
|
+
* Most common use: `(s) => s.toUpperCase()` for fields that are case-
|
|
85
|
+
* insensitive but conventionally uppercase. Runs after filter + maxLength.
|
|
86
|
+
*/
|
|
87
|
+
transform?: (value: string) => string;
|
|
33
88
|
mask?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Pre-fills the input. Used when the user is editing an already-entered
|
|
91
|
+
* value (e.g. fixing a typo in their ASC Key ID / Issuer ID after a
|
|
92
|
+
* verifying-key failure) so they don't have to retype everything.
|
|
93
|
+
* Backspace works normally to delete from the pre-filled value.
|
|
94
|
+
*/
|
|
95
|
+
initialValue?: string;
|
|
34
96
|
onSubmit: (value: string) => void;
|
|
35
97
|
}>;
|
|
36
98
|
export declare const Header: FC<{
|
|
@@ -6,6 +6,15 @@ export declare function useTerminalSize(): {
|
|
|
6
6
|
};
|
|
7
7
|
export interface OnboardingShellProps {
|
|
8
8
|
appId: string;
|
|
9
|
+
/**
|
|
10
|
+
* iOS-side bundle id default — sourced from `config.appId` (top-level), which
|
|
11
|
+
* is what `cap sync` writes into `PRODUCT_BUNDLE_IDENTIFIER`. Distinct from
|
|
12
|
+
* `appId` above, which `getAppId()` may resolve to
|
|
13
|
+
* `config.plugins.CapacitorUpdater.appId` (a Capgo lookup key — wrong for
|
|
14
|
+
* Apple signing). Threaded down to the iOS OnboardingApp; the Android app
|
|
15
|
+
* ignores it.
|
|
16
|
+
*/
|
|
17
|
+
iosBundleIdInitial: string;
|
|
9
18
|
iosDir: string;
|
|
10
19
|
androidDir: string;
|
|
11
20
|
apikey?: string;
|
|
@@ -3,6 +3,30 @@ export interface SelectOption {
|
|
|
3
3
|
label: string;
|
|
4
4
|
value: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Why the wizard ended up on the no-match recovery menu. Drives the Alert
|
|
8
|
+
* + hint copy in `ImportNoMatchRecoveryStep` so each route gets accurate
|
|
9
|
+
* context — previously the screen claimed "no profile linked to this cert"
|
|
10
|
+
* even when the parent had just logged "Apple linked them to X" (cases 3
|
|
11
|
+
* and 4 below). Set by the parent right before each setStep call; absent
|
|
12
|
+
* (undefined) is treated as the legacy `no-profile-on-disk` default for
|
|
13
|
+
* back-compat with call sites that haven't been audited yet.
|
|
14
|
+
*
|
|
15
|
+
* - 'no-profile-on-disk' : identity picked, no usable on-disk
|
|
16
|
+
* profile, and no ASC key to query Apple.
|
|
17
|
+
* - 'apple-no-cert-match' : findCertIdBySha1 returned null — Apple
|
|
18
|
+
* doesn't recognize this cert.
|
|
19
|
+
* - 'apple-no-profiles-linked' : Apple has the cert but zero profiles
|
|
20
|
+
* linked to it.
|
|
21
|
+
* - 'apple-bundle-mismatch' : Apple has profiles but none target the
|
|
22
|
+
* current app's bundle id.
|
|
23
|
+
* - 'apple-distribution-mismatch': Apple has profiles for this bundle id
|
|
24
|
+
* but none in the requested distribution
|
|
25
|
+
* mode (app_store vs ad_hoc).
|
|
26
|
+
* - 'apple-other' : catch-all when none of the specific
|
|
27
|
+
* filters above explain the empty result.
|
|
28
|
+
*/
|
|
29
|
+
export type NoMatchReason = 'no-profile-on-disk' | 'apple-no-cert-match' | 'apple-no-profiles-linked' | 'apple-bundle-mismatch' | 'apple-distribution-mismatch' | 'apple-other';
|
|
6
30
|
export declare const ImportScanningStep: FC;
|
|
7
31
|
export interface ImportDistributionModeStepProps {
|
|
8
32
|
dense?: boolean;
|
|
@@ -28,11 +52,19 @@ export declare const ImportPickProfileStep: FC<ImportPickProfileStepProps>;
|
|
|
28
52
|
export interface ImportNoMatchRecoveryStepProps {
|
|
29
53
|
identityName: string;
|
|
30
54
|
options: SelectOption[];
|
|
55
|
+
/**
|
|
56
|
+
* Why the wizard ended up here. Optional for back-compat — undefined
|
|
57
|
+
* renders the legacy `no-profile-on-disk` wording.
|
|
58
|
+
*/
|
|
59
|
+
reason?: NoMatchReason;
|
|
60
|
+
/** Concrete iOS bundle id; used by the bundle-mismatch + distribution-mismatch alerts. */
|
|
61
|
+
appId?: string;
|
|
62
|
+
/** Active distribution mode; used by the distribution-mismatch alert. */
|
|
63
|
+
importDistribution?: 'app_store' | 'ad_hoc' | null;
|
|
31
64
|
dense?: boolean;
|
|
32
65
|
onChange: (value: string) => void;
|
|
33
66
|
}
|
|
34
67
|
export declare const ImportNoMatchRecoveryStep: FC<ImportNoMatchRecoveryStepProps>;
|
|
35
|
-
export declare const ImportFetchingProfileStep: FC;
|
|
36
68
|
export declare const ImportCreateProfileOnlyStep: FC;
|
|
37
69
|
export interface ImportExportWarningStepProps {
|
|
38
70
|
identityName: string;
|