eas-cli 0.49.0 → 0.50.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 +42 -42
- package/build/build/build.d.ts +6 -2
- package/build/build/build.js +191 -104
- package/build/build/runBuildAndSubmit.js +5 -1
- package/build/credentials/context.js +5 -0
- package/build/credentials/ios/actions/AscApiKeyUtils.js +0 -1
- package/build/credentials/ios/actions/ConfigureProvisioningProfile.js +1 -1
- package/build/credentials/ios/actions/CreateProvisioningProfile.js +1 -1
- package/build/credentials/ios/appstore/AppStoreApi.d.ts +5 -1
- package/build/credentials/ios/appstore/AppStoreApi.js +38 -15
- package/build/credentials/ios/appstore/ascApiKey.d.ts +21 -5
- package/build/credentials/ios/appstore/ascApiKey.js +28 -12
- package/build/credentials/ios/appstore/authenticate.d.ts +9 -18
- package/build/credentials/ios/appstore/authenticate.js +43 -3
- package/build/credentials/ios/appstore/authenticateTypes.d.ts +42 -0
- package/build/credentials/ios/appstore/authenticateTypes.js +16 -0
- package/build/credentials/ios/appstore/contractMessages.d.ts +3 -0
- package/build/credentials/ios/appstore/contractMessages.js +12 -0
- package/build/credentials/ios/appstore/distributionCertificate.d.ts +1 -1
- package/build/credentials/ios/appstore/ensureAppExists.d.ts +2 -2
- package/build/credentials/ios/appstore/ensureAppExists.js +12 -5
- package/build/credentials/ios/appstore/provisioningProfile.d.ts +1 -1
- package/build/credentials/ios/appstore/provisioningProfileAdhoc.d.ts +1 -1
- package/build/credentials/ios/appstore/pushKey.d.ts +4 -4
- package/build/credentials/ios/appstore/pushKey.js +8 -8
- package/build/credentials/ios/appstore/resolveCredentials.d.ts +10 -1
- package/build/credentials/ios/appstore/resolveCredentials.js +125 -3
- package/build/graphql/generated.d.ts +73 -0
- package/build/graphql/generated.js +16 -1
- package/build/graphql/types/Build.js +4 -0
- package/build/submit/ios/AppProduce.d.ts +0 -1
- package/build/submit/ios/AppProduce.js +5 -6
- package/build/submit/ios/AppSpecificPasswordSource.js +2 -2
- package/build/utils/code-signing.d.ts +0 -5
- package/build/utils/code-signing.js +5 -51
- package/oclif.manifest.json +1 -1
- package/package.json +6 -6
|
@@ -1,30 +1,21 @@
|
|
|
1
1
|
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
2
|
import { RequestContext, Session } from '@expo/apple-utils';
|
|
3
|
+
import { MinimalAscApiKey } from '../credentials';
|
|
4
|
+
import { AppleTeamType, AuthCtx, AuthenticationMode, UserAuthCtx } from './authenticateTypes';
|
|
3
5
|
export declare type Options = {
|
|
4
6
|
appleId?: string;
|
|
5
7
|
teamId?: string;
|
|
8
|
+
teamName?: string;
|
|
9
|
+
teamType?: AppleTeamType;
|
|
10
|
+
ascApiKey?: MinimalAscApiKey;
|
|
6
11
|
/**
|
|
7
12
|
* Can be used to restore the Apple auth state via apple-utils.
|
|
8
13
|
*/
|
|
9
14
|
cookies?: Session.AuthState['cookies'];
|
|
15
|
+
/** Indicates how Apple network requests will be made. */
|
|
16
|
+
mode?: AuthenticationMode;
|
|
10
17
|
};
|
|
11
|
-
export declare
|
|
12
|
-
|
|
13
|
-
name: string;
|
|
14
|
-
inHouse?: boolean;
|
|
15
|
-
};
|
|
16
|
-
export declare type AuthCtx = {
|
|
17
|
-
appleId: string;
|
|
18
|
-
appleIdPassword?: string;
|
|
19
|
-
team: Team;
|
|
20
|
-
/**
|
|
21
|
-
* Defined when using Fastlane
|
|
22
|
-
*/
|
|
23
|
-
fastlaneSession?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Can be used to restore the Apple auth state via apple-utils.
|
|
26
|
-
*/
|
|
27
|
-
authState?: Session.AuthState;
|
|
28
|
-
};
|
|
18
|
+
export declare function isUserAuthCtx(authCtx: AuthCtx | undefined): authCtx is UserAuthCtx;
|
|
19
|
+
export declare function assertUserAuthCtx(authCtx: AuthCtx | undefined): UserAuthCtx;
|
|
29
20
|
export declare function getRequestContext(authCtx: AuthCtx): RequestContext;
|
|
30
21
|
export declare function authenticateAsync(options?: Options): Promise<AuthCtx>;
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.authenticateAsync = exports.getRequestContext = void 0;
|
|
3
|
+
exports.authenticateAsync = exports.getRequestContext = exports.assertUserAuthCtx = exports.isUserAuthCtx = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
6
6
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
7
7
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
8
|
const log_1 = tslib_1.__importDefault(require("../../../log"));
|
|
9
9
|
const prompts_1 = require("../../../prompts");
|
|
10
|
+
const authenticateTypes_1 = require("./authenticateTypes");
|
|
10
11
|
const resolveCredentials_1 = require("./resolveCredentials");
|
|
11
12
|
const APPLE_IN_HOUSE_TEAM_TYPE = 'in-house';
|
|
13
|
+
function isUserAuthCtx(authCtx) {
|
|
14
|
+
return !!authCtx && typeof authCtx.appleId === 'string';
|
|
15
|
+
}
|
|
16
|
+
exports.isUserAuthCtx = isUserAuthCtx;
|
|
17
|
+
function assertUserAuthCtx(authCtx) {
|
|
18
|
+
if (isUserAuthCtx(authCtx)) {
|
|
19
|
+
return authCtx;
|
|
20
|
+
}
|
|
21
|
+
throw new Error('Expected user authentication context (login/password).');
|
|
22
|
+
}
|
|
23
|
+
exports.assertUserAuthCtx = assertUserAuthCtx;
|
|
12
24
|
function getRequestContext(authCtx) {
|
|
13
25
|
var _a;
|
|
14
26
|
(0, assert_1.default)((_a = authCtx.authState) === null || _a === void 0 ? void 0 : _a.context, 'Apple request context must be defined');
|
|
@@ -26,7 +38,7 @@ async function loginAsync(userCredentials = {}, options) {
|
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
40
|
// Resolve the user credentials, optimizing for password-less login.
|
|
29
|
-
const { username, password } = await (0, resolveCredentials_1.
|
|
41
|
+
const { username, password } = await (0, resolveCredentials_1.resolveUserCredentialsAsync)(userCredentials);
|
|
30
42
|
(0, assert_1.default)(username);
|
|
31
43
|
// Clear data
|
|
32
44
|
apple_utils_1.Auth.resetInMemoryData();
|
|
@@ -82,6 +94,35 @@ async function loginWithUserCredentialsAsync({ username, password, teamId, provi
|
|
|
82
94
|
return newSession;
|
|
83
95
|
}
|
|
84
96
|
async function authenticateAsync(options = {}) {
|
|
97
|
+
if (options.mode === authenticateTypes_1.AuthenticationMode.API_KEY) {
|
|
98
|
+
return await authenticateWithApiKeyAsync(options);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
return await authenticateAsUserAsync(options);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.authenticateAsync = authenticateAsync;
|
|
105
|
+
async function authenticateWithApiKeyAsync(options = {}) {
|
|
106
|
+
// Resolve the user credentials, optimizing for password-less login.
|
|
107
|
+
const ascApiKey = await (0, resolveCredentials_1.resolveAscApiKeyAsync)(options.ascApiKey);
|
|
108
|
+
const team = await (0, resolveCredentials_1.resolveAppleTeamAsync)(options);
|
|
109
|
+
const jwtDurationSeconds = 1200; // 20 minutes
|
|
110
|
+
return {
|
|
111
|
+
team,
|
|
112
|
+
authState: {
|
|
113
|
+
context: {
|
|
114
|
+
token: new apple_utils_1.Token({
|
|
115
|
+
key: ascApiKey.keyP8,
|
|
116
|
+
issuerId: ascApiKey.issuerId,
|
|
117
|
+
keyId: ascApiKey.keyId,
|
|
118
|
+
duration: jwtDurationSeconds,
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
ascApiKey,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
async function authenticateAsUserAsync(options = {}) {
|
|
85
126
|
// help keep apple login visually apart from the other operations.
|
|
86
127
|
log_1.default.addNewLineIfNone();
|
|
87
128
|
try {
|
|
@@ -119,7 +160,6 @@ async function authenticateAsync(options = {}) {
|
|
|
119
160
|
throw error;
|
|
120
161
|
}
|
|
121
162
|
}
|
|
122
|
-
exports.authenticateAsync = authenticateAsync;
|
|
123
163
|
function formatTeam({ teamId, name, type }) {
|
|
124
164
|
return {
|
|
125
165
|
id: teamId,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
|
+
import { Session } from '@expo/apple-utils';
|
|
3
|
+
import { MinimalAscApiKey } from '../credentials';
|
|
4
|
+
export declare enum AuthenticationMode {
|
|
5
|
+
/** App Store API requests will be made using the official API via an API key, used for CI environments where 2FA cannot be performed. */
|
|
6
|
+
API_KEY = 0,
|
|
7
|
+
/** Uses cookies based authentication and the unofficial App Store web API, this provides more functionality than the official API but cannot be reliably used in CI because it requires 2FA. */
|
|
8
|
+
USER = 1
|
|
9
|
+
}
|
|
10
|
+
export declare enum AppleTeamType {
|
|
11
|
+
IN_HOUSE = "IN_HOUSE",
|
|
12
|
+
COMPANY_OR_ORGANIZATION = "COMPANY_OR_ORGANIZATION",
|
|
13
|
+
INDIVIDUAL = "INDIVIDUAL"
|
|
14
|
+
}
|
|
15
|
+
export declare type Team = {
|
|
16
|
+
id: string;
|
|
17
|
+
/** Name of the development team, this is undefined when ASC API keys are used instead of cookies for authentication. */
|
|
18
|
+
name?: string;
|
|
19
|
+
inHouse?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare type UserAuthCtx = {
|
|
22
|
+
appleId: string;
|
|
23
|
+
appleIdPassword?: string;
|
|
24
|
+
team: Team;
|
|
25
|
+
/**
|
|
26
|
+
* Defined when using Fastlane
|
|
27
|
+
*/
|
|
28
|
+
fastlaneSession?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Can be used to restore the Apple auth state via apple-utils.
|
|
31
|
+
*/
|
|
32
|
+
authState?: Session.AuthState;
|
|
33
|
+
};
|
|
34
|
+
export declare type ApiKeyAuthCtx = {
|
|
35
|
+
ascApiKey: MinimalAscApiKey;
|
|
36
|
+
team: Team;
|
|
37
|
+
/**
|
|
38
|
+
* Can be used to restore the Apple auth state via apple-utils.
|
|
39
|
+
*/
|
|
40
|
+
authState?: Partial<Session.AuthState>;
|
|
41
|
+
};
|
|
42
|
+
export declare type AuthCtx = UserAuthCtx | ApiKeyAuthCtx;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AppleTeamType = exports.AuthenticationMode = void 0;
|
|
4
|
+
var AuthenticationMode;
|
|
5
|
+
(function (AuthenticationMode) {
|
|
6
|
+
/** App Store API requests will be made using the official API via an API key, used for CI environments where 2FA cannot be performed. */
|
|
7
|
+
AuthenticationMode[AuthenticationMode["API_KEY"] = 0] = "API_KEY";
|
|
8
|
+
/** Uses cookies based authentication and the unofficial App Store web API, this provides more functionality than the official API but cannot be reliably used in CI because it requires 2FA. */
|
|
9
|
+
AuthenticationMode[AuthenticationMode["USER"] = 1] = "USER";
|
|
10
|
+
})(AuthenticationMode = exports.AuthenticationMode || (exports.AuthenticationMode = {}));
|
|
11
|
+
var AppleTeamType;
|
|
12
|
+
(function (AppleTeamType) {
|
|
13
|
+
AppleTeamType["IN_HOUSE"] = "IN_HOUSE";
|
|
14
|
+
AppleTeamType["COMPANY_OR_ORGANIZATION"] = "COMPANY_OR_ORGANIZATION";
|
|
15
|
+
AppleTeamType["INDIVIDUAL"] = "INDIVIDUAL";
|
|
16
|
+
})(AppleTeamType = exports.AppleTeamType || (exports.AppleTeamType = {}));
|
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
import { ITCAgreements, RequestContext } from '@expo/apple-utils';
|
|
3
3
|
import type { Ora } from '../../../ora';
|
|
4
4
|
export declare function formatContractMessage(message: ITCAgreements.ITCContractMessage): string;
|
|
5
|
+
/**
|
|
6
|
+
* **Does not support App Store Connect API (CI).**
|
|
7
|
+
*/
|
|
5
8
|
export declare function assertContractMessagesAsync(context: RequestContext, spinner?: Ora): Promise<void>;
|
|
@@ -6,6 +6,9 @@ const apple_utils_1 = require("@expo/apple-utils");
|
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const log_1 = tslib_1.__importDefault(require("../../../log"));
|
|
8
8
|
const convertHTMLToASCII_1 = require("../utils/convertHTMLToASCII");
|
|
9
|
+
/**
|
|
10
|
+
* **Does not support App Store Connect API (CI).**
|
|
11
|
+
*/
|
|
9
12
|
async function getContractStatusAsync(context) {
|
|
10
13
|
var _a;
|
|
11
14
|
try {
|
|
@@ -17,6 +20,9 @@ async function getContractStatusAsync(context) {
|
|
|
17
20
|
return null;
|
|
18
21
|
}
|
|
19
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* **Does not support App Store Connect API (CI).**
|
|
25
|
+
*/
|
|
20
26
|
async function getContractMessagesAsync(context) {
|
|
21
27
|
try {
|
|
22
28
|
return await apple_utils_1.ITCAgreements.getContractMessagesAsync(context);
|
|
@@ -26,6 +32,9 @@ async function getContractMessagesAsync(context) {
|
|
|
26
32
|
return null;
|
|
27
33
|
}
|
|
28
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* **Does not support App Store Connect API (CI).**
|
|
37
|
+
*/
|
|
29
38
|
async function getRequiredContractMessagesAsync(context) {
|
|
30
39
|
var _a, _b;
|
|
31
40
|
// This emulates the check that's performed on the ASC website's "apps"
|
|
@@ -65,6 +74,9 @@ function formatContractMessage(message) {
|
|
|
65
74
|
});
|
|
66
75
|
}
|
|
67
76
|
exports.formatContractMessage = formatContractMessage;
|
|
77
|
+
/**
|
|
78
|
+
* **Does not support App Store Connect API (CI).**
|
|
79
|
+
*/
|
|
68
80
|
async function assertContractMessagesAsync(context, spinner) {
|
|
69
81
|
const { messages, isFatal } = await getRequiredContractMessagesAsync(context);
|
|
70
82
|
if (Array.isArray(messages) && messages.length) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
2
|
import { Certificate, RequestContext } from '@expo/apple-utils';
|
|
3
3
|
import { DistributionCertificate, DistributionCertificateStoreInfo } from './Credentials.types';
|
|
4
|
-
import { AuthCtx } from './
|
|
4
|
+
import { AuthCtx } from './authenticateTypes';
|
|
5
5
|
export declare class AppleTooManyCertsError extends Error {
|
|
6
6
|
}
|
|
7
7
|
export declare function getCertificateBySerialNumberAsync(context: RequestContext, serialNumber: string): Promise<Certificate>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
2
|
import { App, BundleId } from '@expo/apple-utils';
|
|
3
3
|
import { JSONObject } from '@expo/json-file';
|
|
4
|
-
import { AuthCtx } from './
|
|
4
|
+
import { AuthCtx, UserAuthCtx } from './authenticateTypes';
|
|
5
5
|
export interface IosCapabilitiesOptions {
|
|
6
6
|
entitlements: JSONObject;
|
|
7
7
|
}
|
|
@@ -17,7 +17,7 @@ export declare function ensureBundleIdExistsWithNameAsync(authCtx: AuthCtx, { na
|
|
|
17
17
|
}, options?: IosCapabilitiesOptions): Promise<void>;
|
|
18
18
|
export declare function syncCapabilitiesAsync(bundleId: BundleId, { entitlements }: IosCapabilitiesOptions): Promise<void>;
|
|
19
19
|
export declare function syncCapabilityIdentifiersAsync(bundleId: BundleId, { entitlements }: IosCapabilitiesOptions): Promise<void>;
|
|
20
|
-
export declare function ensureAppExistsAsync(
|
|
20
|
+
export declare function ensureAppExistsAsync(userAuthCtx: UserAuthCtx, { name, language, companyName, bundleIdentifier, sku, }: {
|
|
21
21
|
name: string;
|
|
22
22
|
language?: string;
|
|
23
23
|
companyName?: string;
|
|
@@ -44,7 +44,12 @@ async function ensureBundleIdExistsWithNameAsync(authCtx, { name, bundleIdentifi
|
|
|
44
44
|
if (err.message.match(/forbidden for security reasons/) ||
|
|
45
45
|
// Unable to process request - PLA Update available - You currently don't have access to this membership resource. To resolve this issue, agree to the latest Program License Agreement in your developer account.
|
|
46
46
|
err.message.match(/agree/)) {
|
|
47
|
-
|
|
47
|
+
if ((0, authenticate_1.isUserAuthCtx)(authCtx)) {
|
|
48
|
+
await (0, contractMessages_1.assertContractMessagesAsync)(context);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
log_1.default.warn(`You currently don't have access to this membership resource. To resolve this issue, agree to the latest Program License Agreement in your developer account.`);
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
throw err;
|
|
@@ -95,9 +100,9 @@ async function syncCapabilityIdentifiersAsync(bundleId, { entitlements }) {
|
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
102
|
exports.syncCapabilityIdentifiersAsync = syncCapabilityIdentifiersAsync;
|
|
98
|
-
async function ensureAppExistsAsync(
|
|
103
|
+
async function ensureAppExistsAsync(userAuthCtx, { name, language, companyName, bundleIdentifier, sku, }) {
|
|
99
104
|
var _a;
|
|
100
|
-
const context = (0, authenticate_1.getRequestContext)(
|
|
105
|
+
const context = (0, authenticate_1.getRequestContext)(userAuthCtx);
|
|
101
106
|
const spinner = (0, ora_1.ora)(`Linking to App Store Connect ${chalk_1.default.dim(bundleIdentifier)}`).start();
|
|
102
107
|
let app = await apple_utils_1.App.findAsync(context, { bundleId: bundleIdentifier });
|
|
103
108
|
if (!app) {
|
|
@@ -105,6 +110,9 @@ async function ensureAppExistsAsync(authCtx, { name, language, companyName, bund
|
|
|
105
110
|
try {
|
|
106
111
|
// Assert contract errors when the user needs to create an app.
|
|
107
112
|
await (0, contractMessages_1.assertContractMessagesAsync)(context, spinner);
|
|
113
|
+
/**
|
|
114
|
+
* **Does not support App Store Connect API (CI).**
|
|
115
|
+
*/
|
|
108
116
|
app = await apple_utils_1.App.createAsync(context, {
|
|
109
117
|
bundleId: bundleIdentifier,
|
|
110
118
|
name,
|
|
@@ -115,8 +123,7 @@ async function ensureAppExistsAsync(authCtx, { name, language, companyName, bund
|
|
|
115
123
|
}
|
|
116
124
|
catch (error) {
|
|
117
125
|
if (error.message.match(/An App ID with Identifier '(.*)' is not available/)) {
|
|
118
|
-
|
|
119
|
-
throw new Error(`\nThe bundle identifier "${bundleIdentifier}" is not available to provider "${providerName}". Please change it in your app config and try again.\n`);
|
|
126
|
+
throw new Error(`\nThe bundle identifier "${bundleIdentifier}" is not available to provider "${(_a = userAuthCtx.authState) === null || _a === void 0 ? void 0 : _a.session.provider.name}. Please change it in your app config and try again.\n`);
|
|
120
127
|
}
|
|
121
128
|
spinner.fail(`Failed to create App Store app ${chalk_1.default.dim(name)}`);
|
|
122
129
|
error.message +=
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DistributionCertificate, ProvisioningProfile, ProvisioningProfileStoreInfo } from './Credentials.types';
|
|
2
|
-
import { AuthCtx } from './
|
|
2
|
+
import { AuthCtx } from './authenticateTypes';
|
|
3
3
|
export declare enum ProfileClass {
|
|
4
4
|
Adhoc = "ad_hoc",
|
|
5
5
|
General = "general"
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ProvisioningProfile } from './Credentials.types';
|
|
2
|
-
import { AuthCtx } from './
|
|
2
|
+
import { AuthCtx } from './authenticateTypes';
|
|
3
3
|
export declare function createOrReuseAdhocProvisioningProfileAsync(authCtx: AuthCtx, udids: string[], bundleIdentifier: string, distCertSerialNumber: string): Promise<ProvisioningProfile>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { PushKey, PushKeyStoreInfo } from './Credentials.types';
|
|
2
|
-
import {
|
|
2
|
+
import { UserAuthCtx } from './authenticateTypes';
|
|
3
3
|
export declare const APPLE_KEYS_TOO_MANY_GENERATED_ERROR: string;
|
|
4
4
|
/**
|
|
5
5
|
* List all existing push keys on Apple servers.
|
|
6
6
|
* **Does not support App Store Connect API (CI).**
|
|
7
7
|
*/
|
|
8
|
-
export declare function listPushKeysAsync(
|
|
8
|
+
export declare function listPushKeysAsync(userAuthCtx: UserAuthCtx): Promise<PushKeyStoreInfo[]>;
|
|
9
9
|
/**
|
|
10
10
|
* Create a new push key on Apple servers.
|
|
11
11
|
* **Does not support App Store Connect API (CI).**
|
|
12
12
|
*/
|
|
13
|
-
export declare function createPushKeyAsync(
|
|
13
|
+
export declare function createPushKeyAsync(userAuthCtx: UserAuthCtx, name?: string): Promise<PushKey>;
|
|
14
14
|
/**
|
|
15
15
|
* Revoke an existing push key on Apple servers.
|
|
16
16
|
* **Does not support App Store Connect API (CI).**
|
|
17
17
|
*/
|
|
18
|
-
export declare function revokePushKeyAsync(
|
|
18
|
+
export declare function revokePushKeyAsync(userAuthCtx: UserAuthCtx, ids: string[]): Promise<void>;
|
|
@@ -18,10 +18,10 @@ Please remember that Apple Keys are not application specific!
|
|
|
18
18
|
* List all existing push keys on Apple servers.
|
|
19
19
|
* **Does not support App Store Connect API (CI).**
|
|
20
20
|
*/
|
|
21
|
-
async function listPushKeysAsync(
|
|
21
|
+
async function listPushKeysAsync(userAuthCtx) {
|
|
22
22
|
const spinner = (0, ora_1.ora)(`Fetching Apple push keys`).start();
|
|
23
23
|
try {
|
|
24
|
-
const context = (0, authenticate_1.getRequestContext)(
|
|
24
|
+
const context = (0, authenticate_1.getRequestContext)(userAuthCtx);
|
|
25
25
|
const keys = await apple_utils_1.Keys.getKeysAsync(context);
|
|
26
26
|
spinner.succeed(`Fetched Apple push keys`);
|
|
27
27
|
return keys;
|
|
@@ -36,19 +36,19 @@ exports.listPushKeysAsync = listPushKeysAsync;
|
|
|
36
36
|
* Create a new push key on Apple servers.
|
|
37
37
|
* **Does not support App Store Connect API (CI).**
|
|
38
38
|
*/
|
|
39
|
-
async function createPushKeyAsync(
|
|
39
|
+
async function createPushKeyAsync(userAuthCtx, name = `Expo Push Notifications Key ${(0, dateformat_1.default)('yyyymmddHHMMss')}`) {
|
|
40
40
|
var _a;
|
|
41
41
|
const spinner = (0, ora_1.ora)(`Creating Apple push key`).start();
|
|
42
42
|
try {
|
|
43
|
-
const context = (0, authenticate_1.getRequestContext)(
|
|
43
|
+
const context = (0, authenticate_1.getRequestContext)(userAuthCtx);
|
|
44
44
|
const key = await apple_utils_1.Keys.createKeyAsync(context, { name, isApns: true });
|
|
45
45
|
const apnsKeyP8 = await apple_utils_1.Keys.downloadKeyAsync(context, { id: key.id });
|
|
46
46
|
spinner.succeed(`Created Apple push key`);
|
|
47
47
|
return {
|
|
48
48
|
apnsKeyId: key.id,
|
|
49
49
|
apnsKeyP8,
|
|
50
|
-
teamId:
|
|
51
|
-
teamName:
|
|
50
|
+
teamId: userAuthCtx.team.id,
|
|
51
|
+
teamName: userAuthCtx.team.name,
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
catch (err) {
|
|
@@ -66,11 +66,11 @@ exports.createPushKeyAsync = createPushKeyAsync;
|
|
|
66
66
|
* Revoke an existing push key on Apple servers.
|
|
67
67
|
* **Does not support App Store Connect API (CI).**
|
|
68
68
|
*/
|
|
69
|
-
async function revokePushKeyAsync(
|
|
69
|
+
async function revokePushKeyAsync(userAuthCtx, ids) {
|
|
70
70
|
const name = `Apple push key${(ids === null || ids === void 0 ? void 0 : ids.length) === 1 ? '' : 's'}`;
|
|
71
71
|
const spinner = (0, ora_1.ora)(`Revoking ${name}`).start();
|
|
72
72
|
try {
|
|
73
|
-
const context = (0, authenticate_1.getRequestContext)(
|
|
73
|
+
const context = (0, authenticate_1.getRequestContext)(userAuthCtx);
|
|
74
74
|
await Promise.all(ids.map(id => apple_utils_1.Keys.revokeKeyAsync(context, { id })));
|
|
75
75
|
spinner.succeed(`Revoked ${name}`);
|
|
76
76
|
}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
2
|
import { Auth } from '@expo/apple-utils';
|
|
3
|
+
import { MinimalAscApiKey } from '../credentials';
|
|
4
|
+
import { AppleTeamType, Team } from './authenticateTypes';
|
|
3
5
|
/**
|
|
4
6
|
* Get the username and possibly the password from the environment variables or the supplied options.
|
|
5
7
|
* Password is optional because it's only needed for authentication, but not for re-authentication.
|
|
6
8
|
*
|
|
7
9
|
* @param options
|
|
8
10
|
*/
|
|
9
|
-
export declare function
|
|
11
|
+
export declare function resolveUserCredentialsAsync(options: Partial<Auth.UserCredentials>): Promise<Partial<Auth.UserCredentials>>;
|
|
12
|
+
export declare function hasAscEnvVars(): boolean;
|
|
13
|
+
export declare function resolveAscApiKeyAsync(ascApiKey?: MinimalAscApiKey): Promise<MinimalAscApiKey>;
|
|
14
|
+
export declare function resolveAppleTeamAsync(options?: {
|
|
15
|
+
teamId?: string;
|
|
16
|
+
teamName?: string;
|
|
17
|
+
teamType?: AppleTeamType;
|
|
18
|
+
}): Promise<Team>;
|
|
10
19
|
export declare function promptPasswordAsync({ username, }: Pick<Auth.UserCredentials, 'username'>): Promise<string>;
|
|
11
20
|
export declare function deletePasswordAsync({ username, }: Pick<Auth.UserCredentials, 'username'>): Promise<boolean>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deletePasswordAsync = exports.promptPasswordAsync = exports.
|
|
3
|
+
exports.deletePasswordAsync = exports.promptPasswordAsync = exports.resolveAppleTeamAsync = exports.resolveAscApiKeyAsync = exports.hasAscEnvVars = exports.resolveUserCredentialsAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -8,6 +8,7 @@ const fs = tslib_1.__importStar(require("fs-extra"));
|
|
|
8
8
|
const wrap_ansi_1 = tslib_1.__importDefault(require("wrap-ansi"));
|
|
9
9
|
const log_1 = tslib_1.__importStar(require("../../../log"));
|
|
10
10
|
const prompts_1 = require("../../../prompts");
|
|
11
|
+
const authenticateTypes_1 = require("./authenticateTypes");
|
|
11
12
|
const Keychain = tslib_1.__importStar(require("./keychain"));
|
|
12
13
|
/**
|
|
13
14
|
* Get the username and possibly the password from the environment variables or the supplied options.
|
|
@@ -15,14 +16,135 @@ const Keychain = tslib_1.__importStar(require("./keychain"));
|
|
|
15
16
|
*
|
|
16
17
|
* @param options
|
|
17
18
|
*/
|
|
18
|
-
async function
|
|
19
|
+
async function resolveUserCredentialsAsync(options) {
|
|
19
20
|
const credentials = getAppleIdFromEnvironmentOrOptions(options);
|
|
20
21
|
if (!credentials.username) {
|
|
21
22
|
credentials.username = await promptUsernameAsync();
|
|
22
23
|
}
|
|
23
24
|
return credentials;
|
|
24
25
|
}
|
|
25
|
-
exports.
|
|
26
|
+
exports.resolveUserCredentialsAsync = resolveUserCredentialsAsync;
|
|
27
|
+
function hasAscEnvVars() {
|
|
28
|
+
return (!!process.env.EXPO_ASC_API_KEY_PATH ||
|
|
29
|
+
!!process.env.EXPO_ASC_KEY_ID ||
|
|
30
|
+
!!process.env.EXPO_ASC_ISSUER_ID);
|
|
31
|
+
}
|
|
32
|
+
exports.hasAscEnvVars = hasAscEnvVars;
|
|
33
|
+
async function resolveAscApiKeyAsync(ascApiKey) {
|
|
34
|
+
const passedKeyP8 = await getAscKeyP8FromEnvironmentOrOptionsAsync(ascApiKey);
|
|
35
|
+
const passedKeyId = await getAscKeyIdFromEnvironmentOrOptionsAsync(ascApiKey);
|
|
36
|
+
const passedIssuerId = await getAscIssuerIdFromEnvironmentOrOptionsAsync(ascApiKey);
|
|
37
|
+
return {
|
|
38
|
+
keyP8: passedKeyP8,
|
|
39
|
+
keyId: passedKeyId,
|
|
40
|
+
issuerId: passedIssuerId,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
exports.resolveAscApiKeyAsync = resolveAscApiKeyAsync;
|
|
44
|
+
async function getAscKeyP8FromEnvironmentOrOptionsAsync(ascApiKey) {
|
|
45
|
+
if (ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.keyP8) {
|
|
46
|
+
return ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.keyP8;
|
|
47
|
+
}
|
|
48
|
+
else if (process.env.EXPO_ASC_API_KEY_PATH) {
|
|
49
|
+
return await fs.readFile(process.env.EXPO_ASC_API_KEY_PATH, 'utf-8');
|
|
50
|
+
}
|
|
51
|
+
const { ascApiKeyPath } = await (0, prompts_1.promptAsync)({
|
|
52
|
+
type: 'text',
|
|
53
|
+
name: 'ascApiKeyPath',
|
|
54
|
+
message: `Path to ASC Api Key Path (.p8):`,
|
|
55
|
+
validate: (val) => val !== '',
|
|
56
|
+
});
|
|
57
|
+
return await fs.readFile(ascApiKeyPath, 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
async function getAscKeyIdFromEnvironmentOrOptionsAsync(ascApiKey) {
|
|
60
|
+
if (ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.keyId) {
|
|
61
|
+
return ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.keyId;
|
|
62
|
+
}
|
|
63
|
+
else if (process.env.EXPO_ASC_KEY_ID) {
|
|
64
|
+
return process.env.EXPO_ASC_KEY_ID;
|
|
65
|
+
}
|
|
66
|
+
const { ascApiKeyId } = await (0, prompts_1.promptAsync)({
|
|
67
|
+
type: 'text',
|
|
68
|
+
name: 'ascApiKeyId',
|
|
69
|
+
message: `ASC Api Key ID:`,
|
|
70
|
+
validate: (val) => val !== '',
|
|
71
|
+
});
|
|
72
|
+
return ascApiKeyId;
|
|
73
|
+
}
|
|
74
|
+
async function getAscIssuerIdFromEnvironmentOrOptionsAsync(ascApiKey) {
|
|
75
|
+
if (ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.issuerId) {
|
|
76
|
+
return ascApiKey === null || ascApiKey === void 0 ? void 0 : ascApiKey.issuerId;
|
|
77
|
+
}
|
|
78
|
+
else if (process.env.EXPO_ASC_ISSUER_ID) {
|
|
79
|
+
return process.env.EXPO_ASC_ISSUER_ID;
|
|
80
|
+
}
|
|
81
|
+
const { ascIssuerId } = await (0, prompts_1.promptAsync)({
|
|
82
|
+
type: 'text',
|
|
83
|
+
name: 'ascIssuerId',
|
|
84
|
+
message: `ASC Issuer ID:`,
|
|
85
|
+
validate: (val) => val !== '',
|
|
86
|
+
});
|
|
87
|
+
return ascIssuerId;
|
|
88
|
+
}
|
|
89
|
+
function isAppleTeamType(maybeTeamType) {
|
|
90
|
+
return maybeTeamType in authenticateTypes_1.AppleTeamType;
|
|
91
|
+
}
|
|
92
|
+
function assertAppleTeamType(maybeTeamType) {
|
|
93
|
+
if (!isAppleTeamType(maybeTeamType)) {
|
|
94
|
+
throw new Error(`Invalid Apple Team Type: ${maybeTeamType}. Must be one of ${Object.keys(authenticateTypes_1.AppleTeamType).join(', ')}`);
|
|
95
|
+
}
|
|
96
|
+
return maybeTeamType;
|
|
97
|
+
}
|
|
98
|
+
function resolveAppleTeamTypeFromEnvironment() {
|
|
99
|
+
if (!process.env.EXPO_APPLE_TEAM_TYPE) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return assertAppleTeamType(process.env.EXPO_APPLE_TEAM_TYPE);
|
|
103
|
+
}
|
|
104
|
+
async function getAppleTeamIdFromEnvironmentOrOptionsAsync(options) {
|
|
105
|
+
if (options.teamId) {
|
|
106
|
+
return options.teamId;
|
|
107
|
+
}
|
|
108
|
+
else if (process.env.EXPO_APPLE_TEAM_ID) {
|
|
109
|
+
return process.env.EXPO_APPLE_TEAM_ID;
|
|
110
|
+
}
|
|
111
|
+
const { appleTeamId } = await (0, prompts_1.promptAsync)({
|
|
112
|
+
type: 'text',
|
|
113
|
+
name: 'appleTeamId',
|
|
114
|
+
message: `Apple Team ID:`,
|
|
115
|
+
validate: (val) => val !== '',
|
|
116
|
+
});
|
|
117
|
+
return appleTeamId;
|
|
118
|
+
}
|
|
119
|
+
async function getAppleTeamTypeFromEnvironmentOrOptionsAsync(options) {
|
|
120
|
+
if (options.teamType) {
|
|
121
|
+
return options.teamType;
|
|
122
|
+
}
|
|
123
|
+
const appleTeamTypeFromEnvironment = resolveAppleTeamTypeFromEnvironment();
|
|
124
|
+
if (appleTeamTypeFromEnvironment) {
|
|
125
|
+
return appleTeamTypeFromEnvironment;
|
|
126
|
+
}
|
|
127
|
+
const { appleTeamType } = await (0, prompts_1.promptAsync)({
|
|
128
|
+
type: 'select',
|
|
129
|
+
message: 'Select your Apple Team Type:',
|
|
130
|
+
name: 'appleTeamType',
|
|
131
|
+
choices: [
|
|
132
|
+
{ title: 'Enterprise', value: authenticateTypes_1.AppleTeamType.IN_HOUSE },
|
|
133
|
+
{ title: 'Company/Organization', value: authenticateTypes_1.AppleTeamType.COMPANY_OR_ORGANIZATION },
|
|
134
|
+
{ title: 'Individual', value: authenticateTypes_1.AppleTeamType.INDIVIDUAL },
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
return appleTeamType;
|
|
138
|
+
}
|
|
139
|
+
async function resolveAppleTeamAsync(options = {}) {
|
|
140
|
+
const passedTeamType = await getAppleTeamTypeFromEnvironmentOrOptionsAsync(options);
|
|
141
|
+
return {
|
|
142
|
+
id: await getAppleTeamIdFromEnvironmentOrOptionsAsync(options),
|
|
143
|
+
name: options.teamName,
|
|
144
|
+
inHouse: passedTeamType === authenticateTypes_1.AppleTeamType.IN_HOUSE,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
exports.resolveAppleTeamAsync = resolveAppleTeamAsync;
|
|
26
148
|
function getAppleIdFromEnvironmentOrOptions({ username, password, ...userCredentials }) {
|
|
27
149
|
const passedAppleId = username || process.env.EXPO_APPLE_ID;
|
|
28
150
|
// Only resolve the password if the username was provided.
|