@capgo/cli 8.0.0-alpha.5 → 8.0.0
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/README.md +733 -84
- package/dist/index.js +1132 -317
- package/dist/keychain-export.swift +351 -0
- package/dist/package.json +120 -30
- package/dist/src/ai/analyze.d.ts +48 -0
- package/dist/src/ai/log-capture.d.ts +14 -0
- package/dist/src/ai/prompt.d.ts +1 -0
- package/dist/src/ai/render-markdown.d.ts +12 -0
- package/dist/src/ai/sse.d.ts +5 -0
- package/dist/src/ai/stream-markdown.d.ts +22 -0
- package/dist/src/ai/telemetry.d.ts +39 -0
- package/dist/src/analytics/error-category.d.ts +11 -0
- package/dist/src/analytics/org-resolver.d.ts +11 -0
- package/dist/src/analytics/supabase-perf.d.ts +48 -0
- package/dist/src/analytics/track.d.ts +70 -0
- package/dist/src/api/app.d.ts +17 -8
- package/dist/src/api/channels.d.ts +2442 -2729
- package/dist/src/api/crypto.d.ts +26 -0
- package/dist/src/api/update.d.ts +7 -1
- package/dist/src/api/versions.d.ts +9 -2
- package/dist/src/app/add.d.ts +6 -4
- package/dist/src/app/debug.d.ts +3 -7
- package/dist/src/app/delete.d.ts +1 -2
- package/dist/src/app/info.d.ts +5 -1
- package/dist/src/app/list.d.ts +23 -2
- package/dist/src/app/set.d.ts +0 -1
- package/dist/src/app/setting.d.ts +3 -9
- package/dist/src/app/updateProbe.d.ts +43 -0
- package/dist/src/build/credentials-command.d.ts +89 -0
- package/dist/src/build/credentials-manage.d.ts +7 -0
- package/dist/src/build/credentials.d.ts +78 -0
- package/dist/src/build/env-render.d.ts +8 -0
- package/dist/src/build/last-output-command.d.ts +6 -0
- package/dist/src/build/mobileprovision-parser.d.ts +35 -0
- package/dist/src/build/needed.d.ts +28 -0
- package/dist/src/build/onboarding/ai-fit.d.ts +110 -0
- package/dist/src/build/onboarding/analytics.d.ts +23 -0
- package/dist/src/build/onboarding/android/gcp-api.d.ts +128 -0
- package/dist/src/build/onboarding/android/gradle-parser.d.ts +19 -0
- package/dist/src/build/onboarding/android/keystore.d.ts +77 -0
- package/dist/src/build/onboarding/android/oauth-config.d.ts +24 -0
- package/dist/src/build/onboarding/android/oauth-google.d.ts +134 -0
- package/dist/src/build/onboarding/android/play-api.d.ts +91 -0
- package/dist/src/build/onboarding/android/progress.d.ts +22 -0
- package/dist/src/build/onboarding/android/service-account-validation.d.ts +58 -0
- package/dist/src/build/onboarding/android/types.d.ts +72 -0
- package/dist/src/build/onboarding/android/ui/app.d.ts +17 -0
- package/dist/src/build/onboarding/app-verification.d.ts +86 -0
- package/dist/src/build/onboarding/apple-api.d.ts +234 -0
- package/dist/src/build/onboarding/build-log.d.ts +10 -0
- package/dist/src/build/onboarding/bundle-id-detector.d.ts +117 -0
- package/dist/src/build/onboarding/ci-secrets.d.ts +87 -0
- package/dist/src/build/onboarding/command.d.ts +6 -0
- package/dist/src/build/onboarding/csr.d.ts +33 -0
- package/dist/src/build/onboarding/diff-utils.d.ts +24 -0
- package/dist/src/build/onboarding/env-export.d.ts +46 -0
- package/dist/src/build/onboarding/error-categories.d.ts +13 -0
- package/dist/src/build/onboarding/file-picker.d.ts +47 -0
- package/dist/src/build/onboarding/macos-signing.d.ts +190 -0
- package/dist/src/build/onboarding/min-terminal-size.d.ts +16 -0
- package/dist/src/build/onboarding/progress.d.ts +51 -0
- package/dist/src/build/onboarding/recovery.d.ts +7 -0
- package/dist/src/build/onboarding/telemetry.d.ts +28 -0
- package/dist/src/build/onboarding/types.d.ts +140 -0
- package/dist/src/build/onboarding/ui/app.d.ts +36 -0
- package/dist/src/build/onboarding/ui/completed-steps-log.d.ts +9 -0
- package/dist/src/build/onboarding/ui/components.d.ts +178 -0
- package/dist/src/build/onboarding/ui/frame-fit.d.ts +10 -0
- package/dist/src/build/onboarding/ui/min-size-gate.d.ts +20 -0
- package/dist/src/build/onboarding/ui/platform-picker.d.ts +19 -0
- package/dist/src/build/onboarding/ui/shell.d.ts +33 -0
- package/dist/src/build/onboarding/ui/steps/android-ci.d.ts +45 -0
- package/dist/src/build/onboarding/ui/steps/android-keystore.d.ts +75 -0
- package/dist/src/build/onboarding/ui/steps/android-sa-gcp.d.ts +85 -0
- package/dist/src/build/onboarding/ui/steps/android-shared.d.ts +67 -0
- package/dist/src/build/onboarding/ui/steps/ios-ci.d.ts +44 -0
- package/dist/src/build/onboarding/ui/steps/ios-credentials.d.ts +66 -0
- package/dist/src/build/onboarding/ui/steps/ios-import.d.ts +79 -0
- package/dist/src/build/onboarding/ui/steps/ios-shared.d.ts +93 -0
- package/dist/src/build/onboarding/workflow-generator.d.ts +48 -0
- package/dist/src/build/onboarding/workflow-ui-helpers.d.ts +18 -0
- package/dist/src/build/onboarding/workflow-writer.d.ts +36 -0
- package/dist/src/build/output-record.d.ts +30 -0
- package/dist/src/build/pbxproj-parser.d.ts +48 -0
- package/dist/src/build/platform-paths.d.ts +20 -0
- package/dist/src/build/qr.d.ts +5 -0
- package/dist/src/build/request.d.ts +102 -43
- package/dist/src/build/telemetry.d.ts +17 -0
- package/dist/src/bundle/builder-cta.d.ts +67 -0
- package/dist/src/bundle/check.d.ts +0 -1
- package/dist/src/bundle/cleanup.d.ts +3 -12
- package/dist/src/bundle/compatibility.d.ts +23 -12
- package/dist/src/bundle/decrypt.d.ts +4 -0
- package/dist/src/bundle/delete.d.ts +3 -8
- package/dist/src/bundle/encrypt.d.ts +4 -0
- package/dist/src/bundle/list.d.ts +5 -2
- package/dist/src/bundle/partial.d.ts +5 -3
- package/dist/src/bundle/releaseType.d.ts +15 -0
- package/dist/src/bundle/unlink.d.ts +6 -5
- package/dist/src/bundle/upload-command.d.ts +8 -0
- package/dist/src/bundle/upload.d.ts +21 -14
- package/dist/src/bundle/upload_interface.d.ts +2 -50
- package/dist/src/bundle/zip.d.ts +4 -19
- package/dist/src/capacitor-cli.d.ts +13 -0
- package/dist/src/channel/add.d.ts +8 -10
- package/dist/src/channel/currentBundle.d.ts +3 -9
- package/dist/src/channel/delete.d.ts +3 -9
- package/dist/src/channel/list.d.ts +31 -4
- package/dist/src/channel/set.d.ts +2 -17
- package/dist/src/checksum.d.ts +1 -2
- package/dist/src/config/index.d.ts +2 -13
- package/dist/src/docs.d.ts +0 -1
- package/dist/src/github-command.d.ts +9 -0
- package/dist/src/github.d.ts +40 -0
- package/dist/src/index.d.ts +0 -1
- package/dist/src/init/app-conflict.d.ts +2 -0
- package/dist/src/init/command.d.ts +57 -0
- package/dist/src/init/index.d.ts +1 -0
- package/dist/src/init/prompts.d.ts +41 -0
- package/dist/src/init/runtime.d.ts +111 -0
- package/dist/src/init/ui/app.d.ts +9 -0
- package/dist/src/init/ui/components.d.ts +31 -0
- package/dist/src/init/ui.d.ts +12 -0
- package/dist/src/init/updater.d.ts +13 -0
- package/dist/src/key.d.ts +16 -0
- package/dist/src/login.d.ts +0 -1
- package/dist/src/mcp/server.d.ts +5 -0
- package/dist/src/onboarding-support.d.ts +18 -0
- package/dist/src/organization/add.d.ts +26 -0
- package/dist/src/organization/delete.d.ts +3 -0
- package/dist/src/{organisation → organization}/index.d.ts +1 -1
- package/dist/src/{organisation → organization}/list.d.ts +14 -2
- package/dist/src/organization/members.d.ts +12 -0
- package/dist/src/organization/set.d.ts +21 -0
- package/dist/src/posthog.d.ts +13 -0
- package/dist/src/probe.d.ts +20 -0
- package/dist/src/promptPreferences.d.ts +13 -0
- package/dist/src/replicationProgress.d.ts +8 -0
- package/dist/src/run/device.d.ts +5 -0
- package/dist/src/runner-command.d.ts +5 -0
- package/dist/src/schemas/app.d.ts +26 -0
- package/dist/src/schemas/base.d.ts +7 -0
- package/dist/src/schemas/build.d.ts +196 -0
- package/dist/src/schemas/bundle.d.ts +157 -0
- package/dist/src/schemas/channel.d.ts +62 -0
- package/dist/src/schemas/common.d.ts +46 -0
- package/dist/src/schemas/config.d.ts +20 -0
- package/dist/src/schemas/index.d.ts +19 -0
- package/dist/src/schemas/organization.d.ts +41 -0
- package/dist/src/schemas/sdk.d.ts +335 -0
- package/dist/src/schemas/validate.d.ts +12 -0
- package/dist/src/sdk.d.ts +69 -337
- package/dist/src/sdk.js +542 -301
- package/dist/src/terminal-table.d.ts +7 -0
- package/dist/src/types/supabase.types.d.ts +2770 -296
- package/dist/src/updaterConfig.d.ts +8 -0
- package/dist/src/user/account.d.ts +0 -1
- package/dist/src/utils/latest-version.d.ts +0 -1
- package/dist/src/utils/safeWrites.d.ts +21 -0
- package/dist/src/utils/security_policy_errors.d.ts +47 -0
- package/dist/src/utils.d.ts +2869 -341
- package/dist/src/versionHelpers.d.ts +19 -0
- package/package.json +120 -30
- package/skills/native-builds/SKILL.md +255 -0
- package/skills/organization-management/SKILL.md +93 -0
- package/skills/release-management/SKILL.md +225 -0
- package/skills/usage/SKILL.md +92 -0
- package/dist/src/api/app.d.ts.map +0 -1
- package/dist/src/api/channels.d.ts.map +0 -1
- package/dist/src/api/cryptoV2.d.ts +0 -16
- package/dist/src/api/cryptoV2.d.ts.map +0 -1
- package/dist/src/api/update.d.ts.map +0 -1
- package/dist/src/api/versions.d.ts.map +0 -1
- package/dist/src/app/add.d.ts.map +0 -1
- package/dist/src/app/debug.d.ts.map +0 -1
- package/dist/src/app/delete.d.ts.map +0 -1
- package/dist/src/app/info.d.ts.map +0 -1
- package/dist/src/app/list.d.ts.map +0 -1
- package/dist/src/app/set.d.ts.map +0 -1
- package/dist/src/app/setting.d.ts.map +0 -1
- package/dist/src/build/request.d.ts.map +0 -1
- package/dist/src/bundle/check.d.ts.map +0 -1
- package/dist/src/bundle/cleanup.d.ts.map +0 -1
- package/dist/src/bundle/compatibility.d.ts.map +0 -1
- package/dist/src/bundle/decryptV2.d.ts +0 -13
- package/dist/src/bundle/decryptV2.d.ts.map +0 -1
- package/dist/src/bundle/delete.d.ts.map +0 -1
- package/dist/src/bundle/encryptV2.d.ts +0 -14
- package/dist/src/bundle/encryptV2.d.ts.map +0 -1
- package/dist/src/bundle/list.d.ts.map +0 -1
- package/dist/src/bundle/partial.d.ts.map +0 -1
- package/dist/src/bundle/unlink.d.ts.map +0 -1
- package/dist/src/bundle/upload.d.ts.map +0 -1
- package/dist/src/bundle/upload_interface.d.ts.map +0 -1
- package/dist/src/bundle/zip.d.ts.map +0 -1
- package/dist/src/channel/add.d.ts.map +0 -1
- package/dist/src/channel/currentBundle.d.ts.map +0 -1
- package/dist/src/channel/delete.d.ts.map +0 -1
- package/dist/src/channel/list.d.ts.map +0 -1
- package/dist/src/channel/set.d.ts.map +0 -1
- package/dist/src/checksum.d.ts.map +0 -1
- package/dist/src/config/index.d.ts.map +0 -1
- package/dist/src/docs.d.ts.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/init.d.ts +0 -7
- package/dist/src/init.d.ts.map +0 -1
- package/dist/src/keyV2.d.ts +0 -19
- package/dist/src/keyV2.d.ts.map +0 -1
- package/dist/src/login.d.ts.map +0 -1
- package/dist/src/organisation/add.d.ts +0 -19
- package/dist/src/organisation/add.d.ts.map +0 -1
- package/dist/src/organisation/delete.d.ts +0 -8
- package/dist/src/organisation/delete.d.ts.map +0 -1
- package/dist/src/organisation/index.d.ts.map +0 -1
- package/dist/src/organisation/list.d.ts.map +0 -1
- package/dist/src/organisation/set.d.ts +0 -13
- package/dist/src/organisation/set.d.ts.map +0 -1
- package/dist/src/sdk.d.ts.map +0 -1
- package/dist/src/types/supabase.types.d.ts.map +0 -1
- package/dist/src/user/account.d.ts.map +0 -1
- package/dist/src/utils/latest-version.d.ts.map +0 -1
- package/dist/src/utils.d.ts.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure decision logic for the iOS "verify App Store app" onboarding step.
|
|
3
|
+
*
|
|
4
|
+
* No filesystem, network, or React access — every input (the local Release
|
|
5
|
+
* build ID, the remote App Store Connect apps, and the registered bundle IDs)
|
|
6
|
+
* is passed in so the module stays synchronous and unit-testable, mirroring
|
|
7
|
+
* `decideBuilderCtaSurface` / `shouldBlockIncompatibleUpload` in
|
|
8
|
+
* `cli/src/bundle/builder-cta.ts`.
|
|
9
|
+
*
|
|
10
|
+
* The single invariant the step enforces (always `app_store` mode): an App
|
|
11
|
+
* Store Connect app must exist whose `bundleId` equals the Release build ID.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Classification of why (and whether) the verification invariant is met.
|
|
15
|
+
*
|
|
16
|
+
* - `exact-match` — an ASC app's bundle ID == the Release build ID. Pass.
|
|
17
|
+
* - `wrong-build-id` — apps exist but none match → likely a wrong build ID (Path A).
|
|
18
|
+
* - `no-app-identifier-exists` — no apps at all, but the identifier is already
|
|
19
|
+
* registered in the Developer portal (Path B; the
|
|
20
|
+
* ASC new-app form can select the existing id).
|
|
21
|
+
* - `no-app-unregistered` — no apps at all and the identifier is not yet
|
|
22
|
+
* registered (Path B; register first, then create).
|
|
23
|
+
*
|
|
24
|
+
* `no-apps-in-account` is the umbrella for the `apps.length === 0` cases. We
|
|
25
|
+
* keep it in the union because the analytics/step layer surfaces it as a
|
|
26
|
+
* coarse result, but `classifyAppVerification` deliberately returns the finer
|
|
27
|
+
* registered/unregistered split because that distinction is what changes the
|
|
28
|
+
* actionable Path B wording ("identifier already exists" vs "will be
|
|
29
|
+
* registered"). The umbrella value is therefore never returned by the
|
|
30
|
+
* classifier itself.
|
|
31
|
+
*/
|
|
32
|
+
export type AppVerifyResult = 'exact-match' | 'wrong-build-id' | 'no-app-identifier-exists' | 'no-app-unregistered' | 'no-apps-in-account';
|
|
33
|
+
/** Minimal shape of an App Store Connect app needed for verification. */
|
|
34
|
+
export interface AscAppLike {
|
|
35
|
+
bundleId: string;
|
|
36
|
+
name: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ClassifyAppVerificationInput {
|
|
39
|
+
/** The authoritative Release `PRODUCT_BUNDLE_IDENTIFIER` from the project. */
|
|
40
|
+
releaseBundleId: string;
|
|
41
|
+
/** Apps that actually exist in the user's App Store Connect account. */
|
|
42
|
+
apps: AscAppLike[];
|
|
43
|
+
/** Bundle IDs registered in the Apple Developer portal (diagnostic only). */
|
|
44
|
+
registeredBundleIds: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface ClassifyAppVerificationResult {
|
|
47
|
+
result: AppVerifyResult;
|
|
48
|
+
/** The matched ASC app when `result === 'exact-match'`, else `null`. */
|
|
49
|
+
matchedApp: AscAppLike | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Pure classification of the verification invariant.
|
|
53
|
+
*
|
|
54
|
+
* 1. An app whose `bundleId === releaseBundleId` → `exact-match` (+ that app).
|
|
55
|
+
* 2. Otherwise, if any apps exist → `wrong-build-id` (the build signs an id that
|
|
56
|
+
* matches none of the account's apps).
|
|
57
|
+
* 3. Otherwise (no apps), if `releaseBundleId` is already registered →
|
|
58
|
+
* `no-app-identifier-exists`.
|
|
59
|
+
* 4. Otherwise (no apps, not registered) → `no-app-unregistered`.
|
|
60
|
+
*/
|
|
61
|
+
export declare function classifyAppVerification(input: ClassifyAppVerificationInput): ClassifyAppVerificationResult;
|
|
62
|
+
/** Which resolution path the verification gate is enforcing. */
|
|
63
|
+
export type GatePath = 'fix-build-id' | 'create-app';
|
|
64
|
+
export interface EvaluateGateInput {
|
|
65
|
+
/** Whether the invariant now holds (re-checked live on each Continue). */
|
|
66
|
+
satisfied: boolean;
|
|
67
|
+
/** 1-based count of blocked Continue attempts so far. */
|
|
68
|
+
attempt: number;
|
|
69
|
+
}
|
|
70
|
+
export interface EvaluateGateResult {
|
|
71
|
+
/** Whether the user may proceed past the step. */
|
|
72
|
+
proceed: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* How loud the (still-blocked) warning box should be. `0` when satisfied;
|
|
75
|
+
* otherwise the attempt count clamped to `3` so the escalation tops out
|
|
76
|
+
* instead of growing unbounded.
|
|
77
|
+
*/
|
|
78
|
+
escalationLevel: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Pure gate decision. When the invariant is satisfied the user proceeds with no
|
|
82
|
+
* escalation; otherwise they are blocked and the escalation level is the attempt
|
|
83
|
+
* count capped at {@link MAX_ESCALATION_LEVEL} so the warning box can ramp its
|
|
84
|
+
* treatment without overflowing.
|
|
85
|
+
*/
|
|
86
|
+
export declare function evaluateGate(input: EvaluateGateInput): EvaluateGateResult;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a JWT for App Store Connect API authentication.
|
|
3
|
+
* Uses ES256 algorithm with the .p8 private key.
|
|
4
|
+
*/
|
|
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
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Verify the API key works and try to detect the team ID from existing certificates.
|
|
12
|
+
* Throws on 401/403 with a user-friendly message.
|
|
13
|
+
*/
|
|
14
|
+
export declare function verifyApiKey(token: string): Promise<{
|
|
15
|
+
valid: true;
|
|
16
|
+
teamId: string;
|
|
17
|
+
}>;
|
|
18
|
+
export interface AscDistributionCert {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
serialNumber: string;
|
|
22
|
+
expirationDate: string;
|
|
23
|
+
/**
|
|
24
|
+
* Base64-encoded DER of the certificate. Populated when {@link listDistributionCerts}
|
|
25
|
+
* is called with `includeContent: true` — kept optional so existing callers don't pay
|
|
26
|
+
* the larger payload when they don't need it.
|
|
27
|
+
*/
|
|
28
|
+
certificateContent?: string;
|
|
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;
|
|
74
|
+
/**
|
|
75
|
+
* List all iOS distribution certificates.
|
|
76
|
+
*
|
|
77
|
+
* Set `includeContent: true` when you need to compute the cert's SHA1 for
|
|
78
|
+
* matching against a local Keychain identity ({@link findCertIdBySha1}).
|
|
79
|
+
*/
|
|
80
|
+
export declare function listDistributionCerts(token: string, options?: {
|
|
81
|
+
includeContent?: boolean;
|
|
82
|
+
}): Promise<AscDistributionCert[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Compute the SHA1 hash of an ASC certificate's base64-DER content. Returns
|
|
85
|
+
* the lowercase 40-char hex string used elsewhere as the canonical identity
|
|
86
|
+
* key — matches the SHA1 reported by `security find-identity` on macOS.
|
|
87
|
+
*
|
|
88
|
+
* SECURITY NOTE on SHA1: this is NOT a security primitive. macOS itself
|
|
89
|
+
* reports code-signing identities as cert-DER SHA1 (via `security
|
|
90
|
+
* find-identity`), and we have to use the same hash to look up an Apple-side
|
|
91
|
+
* cert by its on-Mac counterpart. SHA1 here is a non-secret identifier, not
|
|
92
|
+
* a message digest protecting any data. CodeQL's "weak cryptographic
|
|
93
|
+
* algorithm" rule is suppressed for this reason.
|
|
94
|
+
*/
|
|
95
|
+
export declare function computeCertSha1(certificateContentBase64: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Match a local Keychain identity (by its SHA1) against an Apple-side
|
|
98
|
+
* certificate and return the Apple certificate ID needed for profile
|
|
99
|
+
* creation. Returns null if no Apple-side cert matches the SHA1.
|
|
100
|
+
*/
|
|
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>;
|
|
116
|
+
/**
|
|
117
|
+
* List all provisioning profiles linked to a specific Apple-side certificate.
|
|
118
|
+
* Used by the import-flow no-match-recovery menu to surface profiles that
|
|
119
|
+
* exist on Apple but haven't been downloaded to the user's Mac.
|
|
120
|
+
*/
|
|
121
|
+
export interface AscProfileSummary {
|
|
122
|
+
id: string;
|
|
123
|
+
name: string;
|
|
124
|
+
profileType: string;
|
|
125
|
+
profileContent: string;
|
|
126
|
+
expirationDate: string;
|
|
127
|
+
bundleIdentifier: string;
|
|
128
|
+
}
|
|
129
|
+
export declare function listProfilesForCert(token: string, certificateId: string): Promise<AscProfileSummary[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Revoke (delete) a certificate by ID.
|
|
132
|
+
*/
|
|
133
|
+
export declare function revokeCertificate(token: string, certId: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Error thrown when certificate limit is reached.
|
|
136
|
+
* Contains the existing certificates so the UI can ask the user which to revoke.
|
|
137
|
+
*/
|
|
138
|
+
export declare class CertificateLimitError extends Error {
|
|
139
|
+
readonly certificates: AscDistributionCert[];
|
|
140
|
+
constructor(certificates: AscDistributionCert[]);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a distribution certificate using a CSR.
|
|
144
|
+
* Returns the certificate ID, base64 DER content, expiration date, and team ID.
|
|
145
|
+
*
|
|
146
|
+
* Throws CertificateLimitError if the limit is reached, so the UI can ask
|
|
147
|
+
* the user which certificate to revoke.
|
|
148
|
+
*/
|
|
149
|
+
export declare function createCertificate(token: string, csrPem: string): Promise<{
|
|
150
|
+
certificateId: string;
|
|
151
|
+
certificateContent: string;
|
|
152
|
+
expirationDate: string;
|
|
153
|
+
teamId: string;
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* Find an existing bundle ID or register a new one.
|
|
157
|
+
* Returns the Apple resource ID needed for profile creation.
|
|
158
|
+
*/
|
|
159
|
+
export declare function ensureBundleId(token: string, identifier: string): Promise<{
|
|
160
|
+
bundleIdResourceId: string;
|
|
161
|
+
}>;
|
|
162
|
+
/**
|
|
163
|
+
* An App Store Connect app record. Used by the iOS app-verification step to
|
|
164
|
+
* check whether an app exists whose `bundleId` matches the project's Release
|
|
165
|
+
* `PRODUCT_BUNDLE_IDENTIFIER`.
|
|
166
|
+
*/
|
|
167
|
+
export interface AscApp {
|
|
168
|
+
id: string;
|
|
169
|
+
bundleId: string;
|
|
170
|
+
name: string;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Parse a `GET /v1/apps` response into {@link AscApp} records. Tolerant of
|
|
174
|
+
* missing `data`, missing `attributes`, and missing individual fields — Apple
|
|
175
|
+
* omits attributes the API key isn't entitled to see rather than nulling them.
|
|
176
|
+
*/
|
|
177
|
+
export declare function parseAppsResponse(json: any): AscApp[];
|
|
178
|
+
/**
|
|
179
|
+
* Parse a `GET /v1/bundleIds` response into the list of registered identifier
|
|
180
|
+
* strings, dropping any falsy entries (missing `attributes`/`identifier`).
|
|
181
|
+
*/
|
|
182
|
+
export declare function parseBundleIdsResponse(json: any): string[];
|
|
183
|
+
/**
|
|
184
|
+
* List every App Store Connect app visible to the API key, following
|
|
185
|
+
* pagination. Uses the existing {@link ascFetch} — no separate fetch path.
|
|
186
|
+
*/
|
|
187
|
+
export declare function listApps(token: string): Promise<AscApp[]>;
|
|
188
|
+
/**
|
|
189
|
+
* List every registered bundle ID identifier visible to the API key, following
|
|
190
|
+
* pagination. Uses the existing {@link ascFetch} — no separate fetch path.
|
|
191
|
+
*/
|
|
192
|
+
export declare function listBundleIds(token: string): Promise<string[]>;
|
|
193
|
+
/**
|
|
194
|
+
* Get the profile name we use for a given appId.
|
|
195
|
+
*/
|
|
196
|
+
export declare function getCapgoProfileName(appId: string): string;
|
|
197
|
+
/**
|
|
198
|
+
* Find existing provisioning profiles matching our naming convention.
|
|
199
|
+
* Only returns profiles we created (named "Capgo <appId> AppStore").
|
|
200
|
+
*/
|
|
201
|
+
export declare function findCapgoProfiles(token: string, appId: string): Promise<Array<{
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
profileType: string;
|
|
205
|
+
}>>;
|
|
206
|
+
/**
|
|
207
|
+
* Delete a provisioning profile by ID.
|
|
208
|
+
*/
|
|
209
|
+
export declare function deleteProfile(token: string, profileId: string): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Create an App Store provisioning profile linking a certificate and bundle ID.
|
|
212
|
+
* Returns the base64 mobileprovision content.
|
|
213
|
+
*
|
|
214
|
+
* Throws a DuplicateProfileError if duplicate profiles exist, so the caller
|
|
215
|
+
* can ask the user whether to delete them and retry.
|
|
216
|
+
*/
|
|
217
|
+
export declare class DuplicateProfileError extends Error {
|
|
218
|
+
readonly profiles: Array<{
|
|
219
|
+
id: string;
|
|
220
|
+
name: string;
|
|
221
|
+
profileType: string;
|
|
222
|
+
}>;
|
|
223
|
+
constructor(profiles: Array<{
|
|
224
|
+
id: string;
|
|
225
|
+
name: string;
|
|
226
|
+
profileType: string;
|
|
227
|
+
}>);
|
|
228
|
+
}
|
|
229
|
+
export declare function createProfile(token: string, bundleIdResourceId: string, certificateId: string, appId: string): Promise<{
|
|
230
|
+
profileId: string;
|
|
231
|
+
profileName: string;
|
|
232
|
+
profileContent: string;
|
|
233
|
+
expirationDate: string;
|
|
234
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn a raw streamed build-log chunk into clean display lines.
|
|
3
|
+
*
|
|
4
|
+
* Splits on `\n` AND bare `\r` (an in-place redraw becomes its own line rather
|
|
5
|
+
* than fusing with another), strips ANSI/escape/control bytes, trims trailing
|
|
6
|
+
* whitespace, and drops the empty element a trailing newline would add (interior
|
|
7
|
+
* blank lines — e.g. the intentional spacer before the first log line — are
|
|
8
|
+
* kept). A chunk may be a single line or several; callers spread the result.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sanitizeBuildLogLines(chunk: string): string[];
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export type BundleIdSource = 'pbxproj-release' | 'pbxproj-debug' | '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
|
+
* The Debug-config PRODUCT_BUNDLE_IDENTIFIER from project.pbxproj, when a
|
|
13
|
+
* literal value exists. Exposed for the awareness note only — never used to
|
|
14
|
+
* gate. Null when no Debug-config literal value is present.
|
|
15
|
+
*/
|
|
16
|
+
debug: BundleIdCandidate | null;
|
|
17
|
+
/**
|
|
18
|
+
* Info.plist CFBundleIdentifier when it's a literal value (not the common
|
|
19
|
+
* `$(PRODUCT_BUNDLE_IDENTIFIER)` placeholder, which we drop because it
|
|
20
|
+
* adds nothing the pbxproj source doesn't already cover).
|
|
21
|
+
*/
|
|
22
|
+
plist: BundleIdCandidate | null;
|
|
23
|
+
/** capacitor.config.ts/json's appId — always present (it's a required arg). */
|
|
24
|
+
capacitor: BundleIdCandidate;
|
|
25
|
+
/**
|
|
26
|
+
* The best-guess Apple-side bundle ID, picked in priority order:
|
|
27
|
+
* pbxproj-release > pbxproj-fallback > plist > capacitor. Returned for
|
|
28
|
+
* convenience so callers don't have to re-implement the precedence.
|
|
29
|
+
*/
|
|
30
|
+
recommended: BundleIdCandidate;
|
|
31
|
+
/**
|
|
32
|
+
* True when the recommended value differs from capacitor.config.appId.
|
|
33
|
+
* Used by redirectIfMismatch to decide whether to adopt the Release id —
|
|
34
|
+
* when they match, capacitor.config.appId is already the build id.
|
|
35
|
+
*/
|
|
36
|
+
mismatch: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* True only when BOTH a Release-config and a Debug-config literal bundle id
|
|
39
|
+
* were found AND they differ. Drives the "Debug ≠ Release" awareness note;
|
|
40
|
+
* never gates. False when either value is missing or they match.
|
|
41
|
+
*/
|
|
42
|
+
debugReleaseDiffer: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* True when a Release-config PRODUCT_BUNDLE_IDENTIFIER was resolved from
|
|
45
|
+
* pbxproj. When false, the authoritative build ID could not be determined
|
|
46
|
+
* from Release and callers should warn/skip gating rather than gate on a
|
|
47
|
+
* Debug or plist fallback.
|
|
48
|
+
*/
|
|
49
|
+
releaseResolved: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Deduplicated, ordered list of candidates ready to render as Select
|
|
52
|
+
* options. Empty list is impossible (capacitor is always included).
|
|
53
|
+
*/
|
|
54
|
+
candidates: BundleIdCandidate[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parse `PRODUCT_BUNDLE_IDENTIFIER = "..."` lines from pbxproj content,
|
|
58
|
+
* returning the Release and Debug candidates separately.
|
|
59
|
+
*
|
|
60
|
+
* Release is authoritative: when ANY Release-config value exists, `release`
|
|
61
|
+
* is populated and `releaseResolved` is true. The Debug value (when present)
|
|
62
|
+
* is returned alongside via `debug` for the awareness note — it is never
|
|
63
|
+
* promoted to `release`.
|
|
64
|
+
*
|
|
65
|
+
* When no Release config exists, `release` is null and `releaseResolved` is
|
|
66
|
+
* false so callers can detect the no-Release case.
|
|
67
|
+
*/
|
|
68
|
+
export declare function parsePbxprojBundleIds(pbxprojContent: string): {
|
|
69
|
+
release: BundleIdCandidate | null;
|
|
70
|
+
debug: BundleIdCandidate | null;
|
|
71
|
+
releaseResolved: boolean;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Parse `PRODUCT_BUNDLE_IDENTIFIER = "..."` lines from pbxproj content.
|
|
75
|
+
* Returns the Release-config value if present, else the shortest non-Release
|
|
76
|
+
* value as a `pbxproj-fallback`. Returns null when no bundle id can be
|
|
77
|
+
* extracted.
|
|
78
|
+
*
|
|
79
|
+
* Release stays authoritative here: a Release value is never overridden by a
|
|
80
|
+
* Debug value. The no-Release fallback is preserved for backward
|
|
81
|
+
* compatibility — callers that need to distinguish "Release resolved" from
|
|
82
|
+
* "fell back to Debug" should use `parsePbxprojBundleIds` (or the
|
|
83
|
+
* `releaseResolved` flag on `detectIosBundleIds`).
|
|
84
|
+
*
|
|
85
|
+
* Looks like a re-implementation of pbxproj-parser.ts's resolveBundleId, but
|
|
86
|
+
* that one needs an XCConfigurationList id (it walks from a target). This
|
|
87
|
+
* one needs to work standalone given only the file contents — so it
|
|
88
|
+
* collects all PRODUCT_BUNDLE_IDENTIFIER values, groups by adjacent
|
|
89
|
+
* `name = Release`/`name = Debug` markers, and prefers Release. Less
|
|
90
|
+
* accurate for multi-target projects but good enough for the "what should
|
|
91
|
+
* we pre-fill" use case here.
|
|
92
|
+
*/
|
|
93
|
+
export declare function parsePbxprojBundleId(pbxprojContent: string): BundleIdCandidate | null;
|
|
94
|
+
/**
|
|
95
|
+
* Parse Info.plist's CFBundleIdentifier from raw XML.
|
|
96
|
+
* Returns null when the file is empty, when CFBundleIdentifier is absent,
|
|
97
|
+
* or when it's a `$(PRODUCT_BUNDLE_IDENTIFIER)` variable reference (we drop
|
|
98
|
+
* the placeholder so the picker doesn't list a non-actionable option).
|
|
99
|
+
*/
|
|
100
|
+
export declare function parseInfoPlistBundleId(plistContent: string): BundleIdCandidate | null;
|
|
101
|
+
/**
|
|
102
|
+
* Read project.pbxproj and Info.plist from the iOS dir and return all
|
|
103
|
+
* available bundle id candidates, plus the recommended one and a
|
|
104
|
+
* mismatch flag.
|
|
105
|
+
*
|
|
106
|
+
* Filesystem reads are best-effort — when either file is missing or
|
|
107
|
+
* unreadable, we silently skip that source. The capacitor candidate is
|
|
108
|
+
* always present.
|
|
109
|
+
*/
|
|
110
|
+
export declare function detectIosBundleIds(opts: {
|
|
111
|
+
/** Project root (typically `process.cwd()`). */
|
|
112
|
+
cwd: string;
|
|
113
|
+
/** Subdirectory under cwd holding the iOS project (typically "ios"). */
|
|
114
|
+
iosDir: string;
|
|
115
|
+
/** Bundle id read from capacitor.config.ts/json — always known. */
|
|
116
|
+
capacitorAppId: string;
|
|
117
|
+
}): DetectedBundleIds;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { BuildCredentials } from '../../schemas/build.js';
|
|
2
|
+
export type CiSecretProvider = 'github' | 'gitlab';
|
|
3
|
+
export interface CiSecretEntry {
|
|
4
|
+
key: string;
|
|
5
|
+
value: string;
|
|
6
|
+
masked: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CiSecretTarget {
|
|
9
|
+
provider: CiSecretProvider;
|
|
10
|
+
label: string;
|
|
11
|
+
cli: 'gh' | 'glab';
|
|
12
|
+
}
|
|
13
|
+
export interface CiSecretDiscovery {
|
|
14
|
+
targets: CiSecretTarget[];
|
|
15
|
+
setup: CiSecretSetupAdvice[];
|
|
16
|
+
notes: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface CiSecretSetupAdvice {
|
|
19
|
+
target: CiSecretTarget;
|
|
20
|
+
reason: 'not-installed' | 'not-authenticated';
|
|
21
|
+
message: string;
|
|
22
|
+
commands: string[];
|
|
23
|
+
}
|
|
24
|
+
interface CommandRunOptions {
|
|
25
|
+
input?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface CommandRunResult {
|
|
28
|
+
status: number | null;
|
|
29
|
+
stdout: string;
|
|
30
|
+
stderr: string;
|
|
31
|
+
error?: Error;
|
|
32
|
+
}
|
|
33
|
+
export type CommandRunner = (command: string, args: string[], options?: CommandRunOptions) => CommandRunResult;
|
|
34
|
+
/**
|
|
35
|
+
* Async runner. Used by the wizard so spawned `gh` / `glab` calls don't block
|
|
36
|
+
* the Node event loop — without this, `ink-spinner`'s animation freezes for
|
|
37
|
+
* the entire duration of every shell-out, which feels like the wizard has hung.
|
|
38
|
+
*
|
|
39
|
+
* Tests can pass either a sync (CommandRunner) or async runner — every helper
|
|
40
|
+
* that calls runner.* does so via `await` so a sync runner returning a plain
|
|
41
|
+
* result still works (Promise.resolve coerces it).
|
|
42
|
+
*/
|
|
43
|
+
export type AsyncCommandRunner = (command: string, args: string[], options?: CommandRunOptions) => CommandRunResult | Promise<CommandRunResult>;
|
|
44
|
+
export declare function runCommand(command: string, args: string[], options?: CommandRunOptions): CommandRunResult;
|
|
45
|
+
/**
|
|
46
|
+
* Non-blocking shell-out. Mirrors `runCommand`'s shape but uses `spawn` so
|
|
47
|
+
* the Node event loop is free to tick spinners and process input while gh /
|
|
48
|
+
* glab work. Default for any wizard-side helper that needs to render UI
|
|
49
|
+
* during the call.
|
|
50
|
+
*/
|
|
51
|
+
export declare function runCommandAsync(command: string, args: string[], options?: CommandRunOptions): Promise<CommandRunResult>;
|
|
52
|
+
export declare function createCiSecretEntries(credentials: Partial<BuildCredentials>, apiKey?: string): CiSecretEntry[];
|
|
53
|
+
export declare function detectCiSecretTargets(runner?: CommandRunner): CiSecretDiscovery;
|
|
54
|
+
export declare function getCiSecretTargetLabel(target: CiSecretTarget | null | undefined): string;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the concrete `owner/repo` (GitHub) or `group/project` (GitLab) the
|
|
57
|
+
* `gh` / `glab` CLI will target from the current working directory.
|
|
58
|
+
*
|
|
59
|
+
* Returns null when the CLI can't determine the repo (e.g. cwd is not a git
|
|
60
|
+
* repo, multiple remotes with no `gh-resolved` config, auth scopes missing).
|
|
61
|
+
*
|
|
62
|
+
* The wizard MUST show this string to the user and require explicit
|
|
63
|
+
* confirmation before any `gh secret set` / `glab variable set` runs — those
|
|
64
|
+
* commands silently overwrite without backup, so the user has to know which
|
|
65
|
+
* repo they're about to mutate.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getCiSecretRepoLabel(target: CiSecretTarget, runner?: CommandRunner): string | null;
|
|
68
|
+
/**
|
|
69
|
+
* Non-blocking variant of `getCiSecretRepoLabel`. Identical logic, but
|
|
70
|
+
* `await`s the runner so the event loop can tick during the gh/glab call —
|
|
71
|
+
* lets Ink spinners actually animate during the resolution.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getCiSecretRepoLabelAsync(target: CiSecretTarget, runner?: AsyncCommandRunner): Promise<string | null>;
|
|
74
|
+
export declare function listExistingCiSecretKeys(target: CiSecretTarget, keys: string[], runner?: CommandRunner): string[];
|
|
75
|
+
/** Non-blocking variant of `listExistingCiSecretKeys`. */
|
|
76
|
+
export declare function listExistingCiSecretKeysAsync(target: CiSecretTarget, keys: string[], runner?: AsyncCommandRunner): Promise<string[]>;
|
|
77
|
+
export declare function uploadCiSecrets(target: CiSecretTarget, entries: CiSecretEntry[], existingKeys?: string[], runner?: CommandRunner): void;
|
|
78
|
+
/**
|
|
79
|
+
* Non-blocking variant of `uploadCiSecrets`. Calls `onProgress(current, total,
|
|
80
|
+
* keyName)` before every `gh secret set` / `glab variable set` so the wizard
|
|
81
|
+
* can render "Pushing N of M: <KEY>…" instead of a frozen spinner.
|
|
82
|
+
*
|
|
83
|
+
* Pushes are still sequential — gh/glab don't have a bulk-set API, and
|
|
84
|
+
* parallelising would risk rate limits + makes failure semantics ambiguous.
|
|
85
|
+
*/
|
|
86
|
+
export declare function uploadCiSecretsAsync(target: CiSecretTarget, entries: CiSecretEntry[], existingKeys?: string[], runner?: AsyncCommandRunner, onProgress?: (current: number, total: number, keyName: string) => void): Promise<void>;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface CsrResult {
|
|
2
|
+
csrPem: string;
|
|
3
|
+
privateKeyPem: string;
|
|
4
|
+
}
|
|
5
|
+
export interface P12Result {
|
|
6
|
+
p12Base64: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Generate a 2048-bit RSA key pair and a Certificate Signing Request.
|
|
10
|
+
* The CSR is what Apple needs to create a distribution certificate.
|
|
11
|
+
* The private key must be kept to later create the .p12 file.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateCsr(): CsrResult;
|
|
14
|
+
/**
|
|
15
|
+
* Create a PKCS#12 (.p12) file from Apple's certificate response and the private key.
|
|
16
|
+
*
|
|
17
|
+
* @param certificateContentBase64 - The `certificateContent` field from Apple's
|
|
18
|
+
* POST /v1/certificates response (base64-encoded DER certificate)
|
|
19
|
+
* @param privateKeyPem - The PEM-encoded private key from generateCsr()
|
|
20
|
+
* @param password - Optional password for the .p12 file (defaults to DEFAULT_P12_PASSWORD)
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Extract the Apple team ID from a certificate's subject OU field.
|
|
24
|
+
* More reliable than parsing the certificate name string.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractTeamIdFromCert(certificateContentBase64: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Default P12 password. node-forge P12 with empty password is incompatible
|
|
29
|
+
* with macOS `security import` (MAC verification fails). Using a known
|
|
30
|
+
* non-empty password avoids this issue.
|
|
31
|
+
*/
|
|
32
|
+
export declare const DEFAULT_P12_PASSWORD = "capgo";
|
|
33
|
+
export declare function createP12(certificateContentBase64: string, privateKeyPem: string, password?: string): P12Result;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line-by-line diff utilities for the workflow-file preview viewer.
|
|
3
|
+
*
|
|
4
|
+
* Uses a textbook longest-common-subsequence algorithm. O(m·n) time/space
|
|
5
|
+
* which is fine for the workflow-file scale we expect (≤200 lines either
|
|
6
|
+
* side); no dep needed.
|
|
7
|
+
*/
|
|
8
|
+
export type DiffKind = 'add' | 'del' | 'eq';
|
|
9
|
+
export interface DiffLine {
|
|
10
|
+
kind: DiffKind;
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Compute a line-level diff between `before` and `after`.
|
|
15
|
+
*
|
|
16
|
+
* Returns an ordered list of lines where:
|
|
17
|
+
* - `kind: 'eq'` → present in both, unchanged
|
|
18
|
+
* - `kind: 'add'` → present only in `after` (will be added by the write)
|
|
19
|
+
* - `kind: 'del'` → present only in `before` (will be removed by the write)
|
|
20
|
+
*
|
|
21
|
+
* When `before` is the empty string, every line in `after` is returned as
|
|
22
|
+
* `add` — the natural "new file" rendering.
|
|
23
|
+
*/
|
|
24
|
+
export declare function diffLines(before: string, after: string): DiffLine[];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-onboarding helper to write a single-platform .env file with the build
|
|
3
|
+
* credentials the user just saved. Used on the "No to GitHub Actions setup, but
|
|
4
|
+
* yes to .env export" branch of the wizard.
|
|
5
|
+
*
|
|
6
|
+
* Reuses the renderer from `build credentials manage` so the file format
|
|
7
|
+
* (section comments, .gitignore reminder, provisioning-map base64 fallback)
|
|
8
|
+
* stays identical between the two paths.
|
|
9
|
+
*/
|
|
10
|
+
import type { BuildCredentials } from '../../schemas/build.js';
|
|
11
|
+
export interface EnvExportOpts {
|
|
12
|
+
appId: string;
|
|
13
|
+
platform: 'ios' | 'android';
|
|
14
|
+
credentials: Partial<BuildCredentials>;
|
|
15
|
+
/** Default false — onboarding writes into the global store, not local. */
|
|
16
|
+
local?: boolean;
|
|
17
|
+
/** If absent, defaults to `<cwd>/.env.capgo.<appId>.<platform>`. */
|
|
18
|
+
targetPath?: string;
|
|
19
|
+
/** When true, write even if the file already exists. */
|
|
20
|
+
overwrite?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type EnvExportResult = {
|
|
23
|
+
kind: 'written';
|
|
24
|
+
path: string;
|
|
25
|
+
fieldCount: number;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'exists';
|
|
28
|
+
path: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'empty';
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Resolve where the .env file should land for the given app + platform. Pure —
|
|
34
|
+
* callable before deciding to actually write, so the wizard can show the path
|
|
35
|
+
* in a confirm prompt without committing to write yet.
|
|
36
|
+
*/
|
|
37
|
+
export declare function defaultExportPath(appId: string, platform: 'ios' | 'android'): string;
|
|
38
|
+
/**
|
|
39
|
+
* Write the credentials to a .env file. Caller is responsible for deciding
|
|
40
|
+
* whether the user has consented (no prompts in here — pure file I/O so the
|
|
41
|
+
* Ink wizard owns the UX).
|
|
42
|
+
*
|
|
43
|
+
* Returns `kind: 'exists'` if the target file is already present and
|
|
44
|
+
* `overwrite` was not set — caller can prompt the user and retry.
|
|
45
|
+
*/
|
|
46
|
+
export declare function exportCredentialsToEnv(opts: EnvExportOpts): EnvExportResult;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AndroidOnboardingErrorCategory } from './android/types.js';
|
|
2
|
+
import type { OnboardingErrorCategory, OnboardingStep } from './types.js';
|
|
3
|
+
export declare function mapIosOnboardingError(error: unknown, failedStep?: OnboardingStep): OnboardingErrorCategory;
|
|
4
|
+
export declare function mapAndroidOnboardingError(error: unknown): AndroidOnboardingErrorCategory;
|
|
5
|
+
/**
|
|
6
|
+
* Map a `ValidationResult.kind` from the SA-import validation module onto an
|
|
7
|
+
* AndroidOnboardingErrorCategory so PostHog `Builder Onboarding Step` events
|
|
8
|
+
* for `sa-json-validation-failed` carry an actionable failure dimension.
|
|
9
|
+
*
|
|
10
|
+
* Kept here (alongside `mapAndroidOnboardingError`) so the full SA-error
|
|
11
|
+
* taxonomy lives in one place.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mapSaValidationKindToCategory(kind: 'shape-error' | 'token-error' | 'no-app-access' | 'network-error'): AndroidOnboardingErrorCategory;
|