eas-cli 2.4.1 → 2.5.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 +47 -47
- package/build/analytics/{events.d.ts → AnalyticsManager.d.ts} +32 -3
- package/build/analytics/AnalyticsManager.js +188 -0
- package/build/analytics/common.d.ts +6 -7
- package/build/analytics/common.js +5 -5
- package/build/build/build.js +21 -21
- package/build/build/context.d.ts +3 -2
- package/build/build/createContext.d.ts +3 -1
- package/build/build/createContext.js +7 -5
- package/build/build/local.js +1 -1
- package/build/build/metadata.js +1 -1
- package/build/build/runBuildAndSubmit.d.ts +2 -1
- package/build/build/runBuildAndSubmit.js +5 -2
- package/build/commandUtils/EasCommand.d.ts +19 -2
- package/build/commandUtils/EasCommand.js +31 -17
- package/build/commandUtils/context/AnalyticsContextField.d.ts +5 -0
- package/build/commandUtils/context/AnalyticsContextField.js +10 -0
- package/build/commandUtils/context/ContextField.d.ts +2 -0
- package/build/commands/analytics.js +3 -3
- package/build/commands/build/index.d.ts +1 -0
- package/build/commands/build/index.js +3 -2
- package/build/commands/build/inspect.d.ts +1 -0
- package/build/commands/build/inspect.js +3 -2
- package/build/commands/credentials.d.ts +1 -0
- package/build/commands/credentials.js +3 -2
- package/build/commands/metadata/pull.d.ts +1 -0
- package/build/commands/metadata/pull.js +4 -1
- package/build/commands/metadata/push.d.ts +1 -0
- package/build/commands/metadata/push.js +4 -1
- package/build/commands/project/init.d.ts +3 -0
- package/build/commands/project/init.js +88 -4
- package/build/commands/secret/create.js +5 -5
- package/build/commands/secret/push.d.ts +16 -0
- package/build/commands/secret/push.js +149 -0
- package/build/commands/submit.d.ts +2 -1
- package/build/commands/submit.js +3 -1
- package/build/commands/update/index.js +2 -2
- package/build/commands/update/view.js +1 -14
- package/build/credentials/android/actions/CreateKeystore.js +3 -3
- package/build/credentials/android/utils/keystore.d.ts +2 -1
- package/build/credentials/android/utils/keystore.js +7 -7
- package/build/credentials/context.d.ts +3 -0
- package/build/credentials/context.js +1 -0
- package/build/credentials/ios/actions/AscApiKeyUtils.js +1 -1
- package/build/credentials/ios/appstore/AppStoreApi.d.ts +2 -1
- package/build/credentials/ios/appstore/AppStoreApi.js +2 -2
- package/build/credentials/ios/appstore/ascApiKey.d.ts +3 -2
- package/build/credentials/ios/appstore/ascApiKey.js +7 -7
- package/build/credentials/manager/HelperActions.d.ts +2 -0
- package/build/credentials/manager/ManageAndroid.js +1 -0
- package/build/credentials/manager/ManageIos.js +1 -0
- package/build/credentials/manager/SelectPlatform.d.ts +3 -1
- package/build/credentials/manager/SelectPlatform.js +2 -1
- package/build/metadata/context.d.ts +4 -0
- package/build/metadata/context.js +1 -0
- package/build/metadata/download.js +2 -2
- package/build/metadata/upload.js +2 -2
- package/build/metadata/utils/telemetry.d.ts +2 -2
- package/build/metadata/utils/telemetry.js +3 -4
- package/build/project/projectUtils.js +1 -3
- package/build/project/publish.js +14 -8
- package/build/submit/BaseSubmitter.d.ts +4 -4
- package/build/submit/BaseSubmitter.js +8 -8
- package/build/submit/android/AndroidSubmitter.js +7 -7
- package/build/submit/context.d.ts +4 -2
- package/build/submit/context.js +6 -5
- package/build/submit/ios/IosSubmitter.js +7 -7
- package/build/submit/submit.js +6 -6
- package/build/update/utils.d.ts +1 -0
- package/build/update/utils.js +11 -1
- package/build/user/SessionManager.d.ts +4 -1
- package/build/user/SessionManager.js +10 -13
- package/build/utils/expoCli.d.ts +1 -0
- package/build/utils/expoCli.js +8 -1
- package/build/utils/expodash/intersection.d.ts +1 -0
- package/build/utils/expodash/intersection.js +8 -0
- package/build/vcs/clients/git.js +13 -2
- package/oclif.manifest.json +1 -1
- package/package.json +3 -2
- package/build/analytics/events.js +0 -59
- package/build/analytics/rudderstackClient.d.ts +0 -7
- package/build/analytics/rudderstackClient.js +0 -112
|
@@ -4,7 +4,7 @@ exports.getAscApiKeyInfo = exports.revokeAscApiKeyAsync = exports.createAscApiKe
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
6
6
|
const promise_retry_1 = tslib_1.__importDefault(require("promise-retry"));
|
|
7
|
-
const
|
|
7
|
+
const AnalyticsManager_1 = require("../../../analytics/AnalyticsManager");
|
|
8
8
|
const log_1 = tslib_1.__importStar(require("../../../log"));
|
|
9
9
|
const ora_1 = require("../../../ora");
|
|
10
10
|
const authenticate_1 = require("./authenticate");
|
|
@@ -57,7 +57,7 @@ exports.getAscApiKeyAsync = getAscApiKeyAsync;
|
|
|
57
57
|
* the resource does not exist. We retry with exponential backoff until the key propagates and
|
|
58
58
|
* is available for download.
|
|
59
59
|
* */
|
|
60
|
-
async function downloadWithRetryAsync(key, { minTimeout = 1000, retries = 6, factor = 2, } = {}) {
|
|
60
|
+
async function downloadWithRetryAsync(analytics, key, { minTimeout = 1000, retries = 6, factor = 2, } = {}) {
|
|
61
61
|
const RESOURCE_DOES_NOT_EXIST_MESSAGE = 'The specified resource does not exist - There is no resource of type';
|
|
62
62
|
try {
|
|
63
63
|
const keyP8 = await (0, promise_retry_1.default)(async (retry, number) => {
|
|
@@ -69,7 +69,7 @@ async function downloadWithRetryAsync(key, { minTimeout = 1000, retries = 6, fac
|
|
|
69
69
|
e.message.includes(RESOURCE_DOES_NOT_EXIST_MESSAGE)) {
|
|
70
70
|
const secondsToRetry = Math.pow(factor, number);
|
|
71
71
|
log_1.default.log(`Received an unexpected response from Apple, retrying in ${secondsToRetry} seconds...`);
|
|
72
|
-
|
|
72
|
+
analytics.logEvent(AnalyticsManager_1.SubmissionEvent.API_KEY_DOWNLOAD_RETRY, {
|
|
73
73
|
errorName: e.name,
|
|
74
74
|
reason: e.message,
|
|
75
75
|
retry: number,
|
|
@@ -83,7 +83,7 @@ async function downloadWithRetryAsync(key, { minTimeout = 1000, retries = 6, fac
|
|
|
83
83
|
factor,
|
|
84
84
|
minTimeout,
|
|
85
85
|
});
|
|
86
|
-
|
|
86
|
+
analytics.logEvent(AnalyticsManager_1.SubmissionEvent.API_KEY_DOWNLOAD_SUCCESS, {});
|
|
87
87
|
return keyP8;
|
|
88
88
|
}
|
|
89
89
|
catch (e) {
|
|
@@ -91,7 +91,7 @@ async function downloadWithRetryAsync(key, { minTimeout = 1000, retries = 6, fac
|
|
|
91
91
|
e.message.includes(RESOURCE_DOES_NOT_EXIST_MESSAGE)) {
|
|
92
92
|
log_1.default.warn(`Unable to download Api Key from Apple at this time. Create and upload your key manually by running 'eas credentials' ${(0, log_1.learnMore)('https://expo.fyi/creating-asc-api-key')}`);
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
analytics.logEvent(AnalyticsManager_1.SubmissionEvent.API_KEY_DOWNLOAD_FAIL, {
|
|
95
95
|
errorName: e.name,
|
|
96
96
|
reason: e.message,
|
|
97
97
|
});
|
|
@@ -103,7 +103,7 @@ exports.downloadWithRetryAsync = downloadWithRetryAsync;
|
|
|
103
103
|
* Create an App Store Connect API Key.
|
|
104
104
|
* **Does not support App Store Connect API (CI).**
|
|
105
105
|
*/
|
|
106
|
-
async function createAscApiKeyAsync(userAuthCtx, { nickname, allAppsVisible, roles, keyType, }) {
|
|
106
|
+
async function createAscApiKeyAsync(analytics, userAuthCtx, { nickname, allAppsVisible, roles, keyType, }) {
|
|
107
107
|
const spinner = (0, ora_1.ora)(`Creating App Store Connect API Key.`).start();
|
|
108
108
|
try {
|
|
109
109
|
const context = (0, authenticate_1.getRequestContext)(userAuthCtx);
|
|
@@ -113,7 +113,7 @@ async function createAscApiKeyAsync(userAuthCtx, { nickname, allAppsVisible, rol
|
|
|
113
113
|
roles: roles !== null && roles !== void 0 ? roles : [apple_utils_1.UserRole.ADMIN],
|
|
114
114
|
keyType: keyType !== null && keyType !== void 0 ? keyType : apple_utils_1.ApiKeyType.PUBLIC_API,
|
|
115
115
|
});
|
|
116
|
-
const keyP8 = await downloadWithRetryAsync(key);
|
|
116
|
+
const keyP8 = await downloadWithRetryAsync(analytics, key);
|
|
117
117
|
if (!keyP8) {
|
|
118
118
|
const { nickname, roles } = key.attributes;
|
|
119
119
|
const humanReadableKey = `App Store Connect Key '${nickname}' (${key.id}) with roles {${roles.join(',')}}`;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { Analytics } from '../../analytics/AnalyticsManager';
|
|
1
2
|
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
3
|
import { Actor } from '../../user/User';
|
|
3
4
|
import { CredentialsContext, CredentialsContextProjectInfo } from '../context';
|
|
4
5
|
export interface Action<T = void> {
|
|
5
6
|
actor: Actor;
|
|
6
7
|
graphqlClient: ExpoGraphqlClient;
|
|
8
|
+
analytics: Analytics;
|
|
7
9
|
projectInfo: CredentialsContextProjectInfo | null;
|
|
8
10
|
runAsync(ctx: CredentialsContext): Promise<T>;
|
|
9
11
|
}
|
|
@@ -43,6 +43,7 @@ class ManageAndroid {
|
|
|
43
43
|
projectInfo: this.callingAction.projectInfo,
|
|
44
44
|
user: this.callingAction.actor,
|
|
45
45
|
graphqlClient: this.callingAction.graphqlClient,
|
|
46
|
+
analytics: this.callingAction.analytics,
|
|
46
47
|
env: buildProfile === null || buildProfile === void 0 ? void 0 : buildProfile.env,
|
|
47
48
|
nonInteractive: false,
|
|
48
49
|
});
|
|
@@ -53,6 +53,7 @@ class ManageIos {
|
|
|
53
53
|
projectInfo: this.callingAction.projectInfo,
|
|
54
54
|
user: this.callingAction.actor,
|
|
55
55
|
graphqlClient: this.callingAction.graphqlClient,
|
|
56
|
+
analytics: this.callingAction.analytics,
|
|
56
57
|
env: buildProfile === null || buildProfile === void 0 ? void 0 : buildProfile.env,
|
|
57
58
|
nonInteractive: false,
|
|
58
59
|
});
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { Analytics } from '../../analytics/AnalyticsManager';
|
|
1
2
|
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
3
|
import { Actor } from '../../user/User';
|
|
3
4
|
import { CredentialsContextProjectInfo } from '../context';
|
|
4
5
|
export declare class SelectPlatform {
|
|
5
6
|
readonly actor: Actor;
|
|
6
7
|
readonly graphqlClient: ExpoGraphqlClient;
|
|
8
|
+
readonly analytics: Analytics;
|
|
7
9
|
readonly projectInfo: CredentialsContextProjectInfo | null;
|
|
8
10
|
private readonly flagPlatform?;
|
|
9
|
-
constructor(actor: Actor, graphqlClient: ExpoGraphqlClient, projectInfo: CredentialsContextProjectInfo | null, flagPlatform?: string | undefined);
|
|
11
|
+
constructor(actor: Actor, graphqlClient: ExpoGraphqlClient, analytics: Analytics, projectInfo: CredentialsContextProjectInfo | null, flagPlatform?: string | undefined);
|
|
10
12
|
runAsync(): Promise<void>;
|
|
11
13
|
}
|
|
@@ -5,9 +5,10 @@ const platform_1 = require("../../platform");
|
|
|
5
5
|
const ManageAndroid_1 = require("./ManageAndroid");
|
|
6
6
|
const ManageIos_1 = require("./ManageIos");
|
|
7
7
|
class SelectPlatform {
|
|
8
|
-
constructor(actor, graphqlClient, projectInfo, flagPlatform) {
|
|
8
|
+
constructor(actor, graphqlClient, analytics, projectInfo, flagPlatform) {
|
|
9
9
|
this.actor = actor;
|
|
10
10
|
this.graphqlClient = graphqlClient;
|
|
11
|
+
this.analytics = analytics;
|
|
11
12
|
this.projectInfo = projectInfo;
|
|
12
13
|
this.flagPlatform = flagPlatform;
|
|
13
14
|
}
|
|
@@ -3,6 +3,7 @@ import { App, Session } from '@expo/apple-utils';
|
|
|
3
3
|
import { ExpoConfig } from '@expo/config';
|
|
4
4
|
import { Platform } from '@expo/eas-build-job';
|
|
5
5
|
import { SubmitProfile } from '@expo/eas-json';
|
|
6
|
+
import { Analytics } from '../analytics/AnalyticsManager';
|
|
6
7
|
import { CredentialsContext } from '../credentials/context';
|
|
7
8
|
import { Actor } from '../user/User';
|
|
8
9
|
export declare type MetadataContext = {
|
|
@@ -16,6 +17,8 @@ export declare type MetadataContext = {
|
|
|
16
17
|
user: Actor;
|
|
17
18
|
/** The store credentials manager */
|
|
18
19
|
credentialsCtx: CredentialsContext;
|
|
20
|
+
/** The analytics manager for EAS cli */
|
|
21
|
+
analytics: Analytics;
|
|
19
22
|
/** The app bundle identifier to use for the store */
|
|
20
23
|
bundleIdentifier: string;
|
|
21
24
|
/** Root of the Expo project directory */
|
|
@@ -36,6 +39,7 @@ export declare type MetadataAppStoreAuthentication = {
|
|
|
36
39
|
export declare function createMetadataContextAsync(params: {
|
|
37
40
|
projectDir: string;
|
|
38
41
|
credentialsCtx: CredentialsContext;
|
|
42
|
+
analytics: Analytics;
|
|
39
43
|
exp: ExpoConfig;
|
|
40
44
|
profileName?: string;
|
|
41
45
|
}): Promise<MetadataContext>;
|
|
@@ -24,6 +24,7 @@ async function createMetadataContextAsync(params) {
|
|
|
24
24
|
profile: submitProfile,
|
|
25
25
|
metadataPath: (_b = submitProfile.metadataPath) !== null && _b !== void 0 ? _b : 'store.config.json',
|
|
26
26
|
user,
|
|
27
|
+
analytics: params.analytics,
|
|
27
28
|
credentialsCtx: params.credentialsCtx,
|
|
28
29
|
bundleIdentifier,
|
|
29
30
|
projectDir: params.projectDir,
|
|
@@ -4,7 +4,7 @@ exports.downloadMetadataAsync = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
6
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
-
const
|
|
7
|
+
const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
|
|
8
8
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
9
9
|
const prompts_1 = require("../prompts");
|
|
10
10
|
const tasks_1 = require("./apple/tasks");
|
|
@@ -29,7 +29,7 @@ async function downloadMetadataAsync(metadataCtx) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
const { app, auth } = await (0, context_1.ensureMetadataAppStoreAuthenticatedAsync)(metadataCtx);
|
|
32
|
-
const { unsubscribeTelemetry, executionId } = (0, telemetry_1.subscribeTelemetry)(
|
|
32
|
+
const { unsubscribeTelemetry, executionId } = (0, telemetry_1.subscribeTelemetry)(metadataCtx.analytics, AnalyticsManager_1.MetadataEvent.APPLE_METADATA_DOWNLOAD, { app, auth });
|
|
33
33
|
log_1.default.addNewLineIfNone();
|
|
34
34
|
log_1.default.log('Downloading App Store config...');
|
|
35
35
|
const errors = [];
|
package/build/metadata/upload.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.uploadMetadataAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
5
|
+
const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
|
|
6
6
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
7
7
|
const prompts_1 = require("../prompts");
|
|
8
8
|
const tasks_1 = require("./apple/tasks");
|
|
@@ -18,7 +18,7 @@ async function uploadMetadataAsync(metadataCtx) {
|
|
|
18
18
|
var _a;
|
|
19
19
|
const storeConfig = await loadConfigWithValidationPromptAsync(metadataCtx);
|
|
20
20
|
const { app, auth } = await (0, context_1.ensureMetadataAppStoreAuthenticatedAsync)(metadataCtx);
|
|
21
|
-
const { unsubscribeTelemetry, executionId } = (0, telemetry_1.subscribeTelemetry)(
|
|
21
|
+
const { unsubscribeTelemetry, executionId } = (0, telemetry_1.subscribeTelemetry)(metadataCtx.analytics, AnalyticsManager_1.MetadataEvent.APPLE_METADATA_UPLOAD, { app, auth });
|
|
22
22
|
log_1.default.addNewLineIfNone();
|
|
23
23
|
log_1.default.log('Uploading App Store configuration...');
|
|
24
24
|
const errors = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@expo/apple-utils/ts-declarations/expo__app-store" />
|
|
2
2
|
import { App, Session } from '@expo/apple-utils';
|
|
3
|
-
import { MetadataEvent } from '../../analytics/
|
|
3
|
+
import { Analytics, MetadataEvent } from '../../analytics/AnalyticsManager';
|
|
4
4
|
export declare type TelemetryContext = {
|
|
5
5
|
app: App;
|
|
6
6
|
auth: Partial<Session.AuthState>;
|
|
@@ -10,7 +10,7 @@ export declare type TelemetryContext = {
|
|
|
10
10
|
* When providing the app and auth info, we can scrub that data from the telemetry.
|
|
11
11
|
* Returns an execution ID to group all events of a single run together, and a unsubscribe function.
|
|
12
12
|
*/
|
|
13
|
-
export declare function subscribeTelemetry(event: MetadataEvent, options: TelemetryContext): {
|
|
13
|
+
export declare function subscribeTelemetry(analytics: Analytics, event: MetadataEvent, options: TelemetryContext): {
|
|
14
14
|
/** Unsubscribe the telemetry from all apple-utils events */
|
|
15
15
|
unsubscribeTelemetry: () => void;
|
|
16
16
|
/** The unique id added to all telemetry events from a single execution */
|
|
@@ -3,18 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.makeDataScrubber = exports.subscribeTelemetry = void 0;
|
|
4
4
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
|
-
const events_1 = require("../../analytics/events");
|
|
7
6
|
/**
|
|
8
7
|
* Subscribe the telemetry to the ongoing metadata requests and responses.
|
|
9
8
|
* When providing the app and auth info, we can scrub that data from the telemetry.
|
|
10
9
|
* Returns an execution ID to group all events of a single run together, and a unsubscribe function.
|
|
11
10
|
*/
|
|
12
|
-
function subscribeTelemetry(event, options) {
|
|
11
|
+
function subscribeTelemetry(analytics, event, options) {
|
|
13
12
|
const executionId = (0, uuid_1.v4)();
|
|
14
13
|
const scrubber = makeDataScrubber(options);
|
|
15
14
|
const { interceptors } = (0, apple_utils_1.getRequestClient)();
|
|
16
15
|
const responseInterceptorId = interceptors.response.use(response => {
|
|
17
|
-
|
|
16
|
+
analytics.logEvent(event, {
|
|
18
17
|
executionId,
|
|
19
18
|
type: 'response',
|
|
20
19
|
phase: 'resolved',
|
|
@@ -26,7 +25,7 @@ function subscribeTelemetry(event, options) {
|
|
|
26
25
|
return response;
|
|
27
26
|
}, (error) => {
|
|
28
27
|
var _a, _b, _c;
|
|
29
|
-
|
|
28
|
+
analytics.logEvent(event, {
|
|
30
29
|
executionId,
|
|
31
30
|
type: 'response',
|
|
32
31
|
phase: 'rejected',
|
|
@@ -89,9 +89,7 @@ async function validateAppVersionRuntimePolicySupportAsync(projectDir, exp) {
|
|
|
89
89
|
}
|
|
90
90
|
exports.validateAppVersionRuntimePolicySupportAsync = validateAppVersionRuntimePolicySupportAsync;
|
|
91
91
|
async function installExpoUpdatesAsync(projectDir) {
|
|
92
|
-
log_1.default.
|
|
93
|
-
log_1.default.log(`Running ${chalk_1.default.bold('expo install expo-updates')}`);
|
|
94
|
-
log_1.default.newLine();
|
|
92
|
+
log_1.default.log(chalk_1.default.gray `> npx expo install expo-updates`);
|
|
95
93
|
await (0, expoCli_1.expoCommandAsync)(projectDir, ['install', 'expo-updates']);
|
|
96
94
|
log_1.default.newLine();
|
|
97
95
|
}
|
package/build/project/publish.js
CHANGED
|
@@ -107,14 +107,20 @@ async function buildBundlesAsync({ projectDir, inputDir, }) {
|
|
|
107
107
|
if (!packageJSON) {
|
|
108
108
|
throw new Error('Could not locate package.json');
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
'export',
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
if ((0, expoCli_1.shouldUseVersionedExpoCLI)(projectDir)) {
|
|
111
|
+
await (0, expoCli_1.expoCommandAsync)(projectDir, ['export', '--output-dir', inputDir, '--dump-sourcemap']);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Legacy global Expo CLI
|
|
115
|
+
await (0, expoCli_1.expoCommandAsync)(projectDir, [
|
|
116
|
+
'export',
|
|
117
|
+
'--output-dir',
|
|
118
|
+
inputDir,
|
|
119
|
+
'--experimental-bundle',
|
|
120
|
+
'--non-interactive',
|
|
121
|
+
'--dump-sourcemap',
|
|
122
|
+
]);
|
|
123
|
+
}
|
|
118
124
|
}
|
|
119
125
|
exports.buildBundlesAsync = buildBundlesAsync;
|
|
120
126
|
async function resolveInputDirectoryAsync(customInputDirectory) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Platform } from '@expo/eas-build-job';
|
|
2
|
-
import {
|
|
2
|
+
import { AnalyticsEvent } from '../analytics/AnalyticsManager';
|
|
3
3
|
import { AndroidSubmissionConfigInput, IosSubmissionConfigInput, SubmissionFragment } from '../graphql/generated';
|
|
4
4
|
import { SubmissionContext } from './context';
|
|
5
5
|
export interface SubmissionInput<P extends Platform> {
|
|
@@ -8,9 +8,9 @@ export interface SubmissionInput<P extends Platform> {
|
|
|
8
8
|
buildId?: string;
|
|
9
9
|
}
|
|
10
10
|
interface AnalyticEvents {
|
|
11
|
-
attemptEvent:
|
|
12
|
-
successEvent:
|
|
13
|
-
failureEvent:
|
|
11
|
+
attemptEvent: AnalyticsEvent;
|
|
12
|
+
successEvent: AnalyticsEvent;
|
|
13
|
+
failureEvent: AnalyticsEvent;
|
|
14
14
|
}
|
|
15
15
|
export default abstract class BaseSubmitter<P extends Platform, ResolvedSourceOptions, SubmissionOptions> {
|
|
16
16
|
protected ctx: SubmissionContext<P>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
+
const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
|
|
4
5
|
const common_1 = require("../analytics/common");
|
|
5
|
-
const events_1 = require("../analytics/events");
|
|
6
6
|
const AppPlatform_1 = require("../graphql/types/AppPlatform");
|
|
7
7
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
8
8
|
const ora_1 = require("../ora");
|
|
@@ -20,11 +20,11 @@ class BaseSubmitter {
|
|
|
20
20
|
for (const key in this.sourceOptionResolver) {
|
|
21
21
|
const sourceOptionKey = key;
|
|
22
22
|
const sourceOptionAnalytics = this.sourceOptionAnalytics[sourceOptionKey];
|
|
23
|
-
const sourceOption = await (0, common_1.withAnalyticsAsync)(async () => await this.sourceOptionResolver[sourceOptionKey](), {
|
|
23
|
+
const sourceOption = await (0, common_1.withAnalyticsAsync)(this.ctx.analytics, async () => await this.sourceOptionResolver[sourceOptionKey](), {
|
|
24
24
|
attemptEvent: sourceOptionAnalytics.attemptEvent,
|
|
25
25
|
successEvent: sourceOptionAnalytics.successEvent,
|
|
26
26
|
failureEvent: sourceOptionAnalytics.failureEvent,
|
|
27
|
-
|
|
27
|
+
properties: this.ctx.analyticsEventProperties,
|
|
28
28
|
});
|
|
29
29
|
resolvedSourceOptions[sourceOptionKey] = sourceOption;
|
|
30
30
|
}
|
|
@@ -50,11 +50,11 @@ class BaseSubmitter {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
async createSubmissionWithAnalyticsAsync(submissionInput) {
|
|
53
|
-
return await (0, common_1.withAnalyticsAsync)(async () => this.createSubmissionAsync(submissionInput), {
|
|
54
|
-
attemptEvent:
|
|
55
|
-
successEvent:
|
|
56
|
-
failureEvent:
|
|
57
|
-
|
|
53
|
+
return await (0, common_1.withAnalyticsAsync)(this.ctx.analytics, async () => this.createSubmissionAsync(submissionInput), {
|
|
54
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_REQUEST_ATTEMPT,
|
|
55
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_REQUEST_SUCCESS,
|
|
56
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_REQUEST_FAIL,
|
|
57
|
+
properties: this.ctx.analyticsEventProperties,
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
|
-
const
|
|
5
|
+
const AnalyticsManager_1 = require("../../analytics/AnalyticsManager");
|
|
6
6
|
const SubmissionMutation_1 = require("../../graphql/mutations/SubmissionMutation");
|
|
7
7
|
const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
|
|
8
8
|
const ArchiveSource_1 = require("../ArchiveSource");
|
|
@@ -21,14 +21,14 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
|
|
|
21
21
|
};
|
|
22
22
|
const sourceOptionsAnalytics = {
|
|
23
23
|
archive: {
|
|
24
|
-
attemptEvent:
|
|
25
|
-
successEvent:
|
|
26
|
-
failureEvent:
|
|
24
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_ATTEMPT,
|
|
25
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_SUCCESS,
|
|
26
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_FAIL,
|
|
27
27
|
},
|
|
28
28
|
serviceAccountKeyResult: {
|
|
29
|
-
attemptEvent:
|
|
30
|
-
successEvent:
|
|
31
|
-
failureEvent:
|
|
29
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_ATTEMPT,
|
|
30
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_SUCCESS,
|
|
31
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_FAIL,
|
|
32
32
|
},
|
|
33
33
|
};
|
|
34
34
|
super(ctx, options, sourceOptionsResolver, sourceOptionsAnalytics);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExpoConfig } from '@expo/config';
|
|
2
2
|
import { Platform } from '@expo/eas-build-job';
|
|
3
3
|
import { SubmitProfile } from '@expo/eas-json';
|
|
4
|
-
import {
|
|
4
|
+
import { Analytics, AnalyticsEventProperties } from '../analytics/AnalyticsManager';
|
|
5
5
|
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
6
6
|
import { CredentialsContext } from '../credentials/context';
|
|
7
7
|
import { Actor } from '../user/User';
|
|
@@ -9,7 +9,7 @@ export interface SubmissionContext<T extends Platform> {
|
|
|
9
9
|
accountName: string;
|
|
10
10
|
archiveFlags: SubmitArchiveFlags;
|
|
11
11
|
credentialsCtx: CredentialsContext;
|
|
12
|
-
|
|
12
|
+
analyticsEventProperties: AnalyticsEventProperties;
|
|
13
13
|
exp: ExpoConfig;
|
|
14
14
|
nonInteractive: boolean;
|
|
15
15
|
platform: T;
|
|
@@ -19,6 +19,7 @@ export interface SubmissionContext<T extends Platform> {
|
|
|
19
19
|
projectName: string;
|
|
20
20
|
user: Actor;
|
|
21
21
|
graphqlClient: ExpoGraphqlClient;
|
|
22
|
+
analytics: Analytics;
|
|
22
23
|
applicationIdentifierOverride?: string;
|
|
23
24
|
}
|
|
24
25
|
export interface SubmitArchiveFlags {
|
|
@@ -38,6 +39,7 @@ export declare function createSubmissionContextAsync<T extends Platform>(params:
|
|
|
38
39
|
applicationIdentifier?: string;
|
|
39
40
|
actor: Actor;
|
|
40
41
|
graphqlClient: ExpoGraphqlClient;
|
|
42
|
+
analytics: Analytics;
|
|
41
43
|
exp: ExpoConfig;
|
|
42
44
|
projectId: string;
|
|
43
45
|
}): Promise<SubmissionContext<T>>;
|
package/build/submit/context.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createSubmissionContextAsync = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
|
-
const
|
|
5
|
+
const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
|
|
6
6
|
const context_1 = require("../credentials/context");
|
|
7
7
|
const projectUtils_1 = require("../project/projectUtils");
|
|
8
8
|
async function createSubmissionContextAsync(params) {
|
|
9
|
-
const { applicationIdentifier, projectDir, nonInteractive, actor, exp, projectId, graphqlClient, } = params;
|
|
9
|
+
const { applicationIdentifier, projectDir, nonInteractive, actor, exp, projectId, graphqlClient, analytics, } = params;
|
|
10
10
|
const { env, ...rest } = params;
|
|
11
11
|
const projectName = exp.slug;
|
|
12
12
|
const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
|
|
@@ -17,24 +17,25 @@ async function createSubmissionContextAsync(params) {
|
|
|
17
17
|
projectDir,
|
|
18
18
|
user: actor,
|
|
19
19
|
graphqlClient,
|
|
20
|
+
analytics,
|
|
20
21
|
projectInfo: { exp, projectId },
|
|
21
22
|
nonInteractive,
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
|
-
const
|
|
25
|
+
const analyticsEventProperties = {
|
|
25
26
|
tracking_id: (0, uuid_1.v4)(),
|
|
26
27
|
platform: params.platform,
|
|
27
28
|
...(accountId && { account_id: accountId }),
|
|
28
29
|
project_id: projectId,
|
|
29
30
|
};
|
|
30
|
-
|
|
31
|
+
rest.analytics.logEvent(AnalyticsManager_1.SubmissionEvent.SUBMIT_COMMAND, analyticsEventProperties);
|
|
31
32
|
return {
|
|
32
33
|
...rest,
|
|
33
34
|
accountName: account.name,
|
|
34
35
|
credentialsCtx,
|
|
35
36
|
projectName,
|
|
36
37
|
user: actor,
|
|
37
|
-
|
|
38
|
+
analyticsEventProperties,
|
|
38
39
|
applicationIdentifierOverride: applicationIdentifier,
|
|
39
40
|
};
|
|
40
41
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
|
-
const
|
|
5
|
+
const AnalyticsManager_1 = require("../../analytics/AnalyticsManager");
|
|
6
6
|
const SubmissionMutation_1 = require("../../graphql/mutations/SubmissionMutation");
|
|
7
7
|
const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
|
|
8
8
|
const ArchiveSource_1 = require("../ArchiveSource");
|
|
@@ -36,14 +36,14 @@ class IosSubmitter extends BaseSubmitter_1.default {
|
|
|
36
36
|
};
|
|
37
37
|
const sourceOptionsAnalytics = {
|
|
38
38
|
archive: {
|
|
39
|
-
attemptEvent:
|
|
40
|
-
successEvent:
|
|
41
|
-
failureEvent:
|
|
39
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_ATTEMPT,
|
|
40
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_SUCCESS,
|
|
41
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.GATHER_ARCHIVE_FAIL,
|
|
42
42
|
},
|
|
43
43
|
credentials: {
|
|
44
|
-
attemptEvent:
|
|
45
|
-
successEvent:
|
|
46
|
-
failureEvent:
|
|
44
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_ATTEMPT,
|
|
45
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_SUCCESS,
|
|
46
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.GATHER_CREDENTIALS_FAIL,
|
|
47
47
|
},
|
|
48
48
|
};
|
|
49
49
|
super(ctx, options, sourceOptionsResolver, sourceOptionsAnalytics);
|
package/build/submit/submit.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.exitWithNonZeroCodeIfSomeSubmissionsDidntFinish = exports.waitToComplete
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
|
|
7
8
|
const common_1 = require("../analytics/common");
|
|
8
|
-
const events_1 = require("../analytics/events");
|
|
9
9
|
const generated_1 = require("../graphql/generated");
|
|
10
10
|
const log_1 = tslib_1.__importStar(require("../log"));
|
|
11
11
|
const platform_1 = require("../platform");
|
|
@@ -14,16 +14,16 @@ const IosSubmitCommand_1 = tslib_1.__importDefault(require("./ios/IosSubmitComma
|
|
|
14
14
|
const logs_1 = require("./utils/logs");
|
|
15
15
|
const wait_1 = require("./utils/wait");
|
|
16
16
|
async function submitAsync(ctx) {
|
|
17
|
-
return await (0, common_1.withAnalyticsAsync)(async () => {
|
|
17
|
+
return await (0, common_1.withAnalyticsAsync)(ctx.analytics, async () => {
|
|
18
18
|
const command = ctx.platform === eas_build_job_1.Platform.ANDROID
|
|
19
19
|
? new AndroidSubmitCommand_1.default(ctx)
|
|
20
20
|
: new IosSubmitCommand_1.default(ctx);
|
|
21
21
|
return command.runAsync();
|
|
22
22
|
}, {
|
|
23
|
-
attemptEvent:
|
|
24
|
-
successEvent:
|
|
25
|
-
failureEvent:
|
|
26
|
-
|
|
23
|
+
attemptEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_COMMAND_ATTEMPT,
|
|
24
|
+
successEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_COMMAND_SUCCESS,
|
|
25
|
+
failureEvent: AnalyticsManager_1.SubmissionEvent.SUBMIT_COMMAND_FAIL,
|
|
26
|
+
properties: ctx.analyticsEventProperties,
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
exports.submitAsync = submitAsync;
|
package/build/update/utils.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare type FormattedUpdateGroupDescriptionWithBranch = FormattedUpdateG
|
|
|
22
22
|
};
|
|
23
23
|
export declare const UPDATE_COLUMNS: string[];
|
|
24
24
|
export declare const UPDATE_COLUMNS_WITH_BRANCH: string[];
|
|
25
|
+
export declare function formatUpdateGroup(update: FormattedUpdateGroupDescription): string;
|
|
25
26
|
export declare function getPlatformsForGroup({ group, updates, }: {
|
|
26
27
|
group: string | undefined;
|
|
27
28
|
updates: {
|
package/build/update/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateBuildProfileConfigMatchesProjectConfigAsync = exports.checkEASUpdateURLIsSetAsync = exports.getUpdateGroupDescriptionsWithBranch = exports.getUpdateGroupDescriptions = exports.formatUpdateTitle = exports.ensureValidVersions = exports.formatUpdateMessage = exports.truncateString = exports.formatPlatformForUpdateGroup = exports.getPlatformsForGroup = exports.UPDATE_COLUMNS_WITH_BRANCH = exports.UPDATE_COLUMNS = void 0;
|
|
3
|
+
exports.validateBuildProfileConfigMatchesProjectConfigAsync = exports.checkEASUpdateURLIsSetAsync = exports.getUpdateGroupDescriptionsWithBranch = exports.getUpdateGroupDescriptions = exports.formatUpdateTitle = exports.ensureValidVersions = exports.formatUpdateMessage = exports.truncateString = exports.formatPlatformForUpdateGroup = exports.getPlatformsForGroup = exports.formatUpdateGroup = exports.UPDATE_COLUMNS_WITH_BRANCH = exports.UPDATE_COLUMNS = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const timeago_js_1 = require("@expo/timeago.js");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -11,6 +11,7 @@ const platform_1 = require("../platform");
|
|
|
11
11
|
const prompts_1 = require("../prompts");
|
|
12
12
|
const User_1 = require("../user/User");
|
|
13
13
|
const groupBy_1 = tslib_1.__importDefault(require("../utils/expodash/groupBy"));
|
|
14
|
+
const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
|
|
14
15
|
exports.UPDATE_COLUMNS = [
|
|
15
16
|
'Update message',
|
|
16
17
|
'Update runtime version',
|
|
@@ -18,6 +19,15 @@ exports.UPDATE_COLUMNS = [
|
|
|
18
19
|
'Update platforms',
|
|
19
20
|
];
|
|
20
21
|
exports.UPDATE_COLUMNS_WITH_BRANCH = ['Branch', ...exports.UPDATE_COLUMNS];
|
|
22
|
+
function formatUpdateGroup(update) {
|
|
23
|
+
return (0, formatFields_1.default)([
|
|
24
|
+
{ label: 'Platforms', value: update.platforms },
|
|
25
|
+
{ label: 'Runtime Version', value: update.runtimeVersion },
|
|
26
|
+
{ label: 'Message', value: update.message },
|
|
27
|
+
{ label: 'Group ID', value: update.group },
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
exports.formatUpdateGroup = formatUpdateGroup;
|
|
21
31
|
function getPlatformsForGroup({ group, updates = [], }) {
|
|
22
32
|
const groupedUpdates = (0, groupBy_1.default)(updates, update => update.group);
|
|
23
33
|
return formatPlatformForUpdateGroup(group ? groupedUpdates[group] : undefined);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AnalyticsWithOrchestration } from '../analytics/AnalyticsManager';
|
|
1
2
|
import { CurrentUserQuery } from '../graphql/generated';
|
|
2
3
|
export declare enum UserSecondFactorDeviceMethod {
|
|
3
4
|
AUTHENTICATOR = "authenticator",
|
|
@@ -12,7 +13,9 @@ declare type LoggedInAuthenticationInfo = {
|
|
|
12
13
|
};
|
|
13
14
|
declare type Actor = NonNullable<CurrentUserQuery['meActor']>;
|
|
14
15
|
export default class SessionManager {
|
|
15
|
-
private
|
|
16
|
+
private readonly analytics;
|
|
17
|
+
private currentActor;
|
|
18
|
+
constructor(analytics: AnalyticsWithOrchestration);
|
|
16
19
|
getAccessToken(): string | null;
|
|
17
20
|
getSessionSecret(): string | null;
|
|
18
21
|
private getSession;
|
|
@@ -8,14 +8,12 @@ const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
|
8
8
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
9
9
|
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
10
10
|
const ApiV2Error_1 = require("../ApiV2Error");
|
|
11
|
-
const Analytics = tslib_1.__importStar(require("../analytics/rudderstackClient"));
|
|
12
11
|
const api_1 = require("../api");
|
|
13
12
|
const createGraphqlClient_1 = require("../commandUtils/context/contextUtils/createGraphqlClient");
|
|
14
13
|
const UserQuery_1 = require("../graphql/queries/UserQuery");
|
|
15
14
|
const log_1 = tslib_1.__importStar(require("../log"));
|
|
16
15
|
const prompts_1 = require("../prompts");
|
|
17
16
|
const paths_1 = require("../utils/paths");
|
|
18
|
-
const User_1 = require("./User");
|
|
19
17
|
const fetchSessionSecretAndUser_1 = require("./fetchSessionSecretAndUser");
|
|
20
18
|
var UserSecondFactorDeviceMethod;
|
|
21
19
|
(function (UserSecondFactorDeviceMethod) {
|
|
@@ -23,6 +21,9 @@ var UserSecondFactorDeviceMethod;
|
|
|
23
21
|
UserSecondFactorDeviceMethod["SMS"] = "sms";
|
|
24
22
|
})(UserSecondFactorDeviceMethod = exports.UserSecondFactorDeviceMethod || (exports.UserSecondFactorDeviceMethod = {}));
|
|
25
23
|
class SessionManager {
|
|
24
|
+
constructor(analytics) {
|
|
25
|
+
this.analytics = analytics;
|
|
26
|
+
}
|
|
26
27
|
getAccessToken() {
|
|
27
28
|
var _a;
|
|
28
29
|
return (_a = process.env.EXPO_TOKEN) !== null && _a !== void 0 ? _a : null;
|
|
@@ -50,26 +51,22 @@ class SessionManager {
|
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
53
|
async logoutAsync() {
|
|
53
|
-
this.
|
|
54
|
+
this.currentActor = undefined;
|
|
54
55
|
await this.setSessionAsync(undefined);
|
|
55
56
|
}
|
|
56
57
|
async getUserAsync() {
|
|
57
|
-
if (!this.
|
|
58
|
+
if (!this.currentActor && (this.getAccessToken() || this.getSessionSecret())) {
|
|
58
59
|
const authenticationInfo = {
|
|
59
60
|
accessToken: this.getAccessToken(),
|
|
60
61
|
sessionSecret: this.getSessionSecret(),
|
|
61
62
|
};
|
|
62
|
-
const
|
|
63
|
-
this.
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
username: (0, User_1.getActorDisplayName)(user),
|
|
67
|
-
user_id: user.id,
|
|
68
|
-
user_type: user.__typename,
|
|
69
|
-
});
|
|
63
|
+
const actor = await UserQuery_1.UserQuery.currentUserAsync((0, createGraphqlClient_1.createGraphqlClient)(authenticationInfo));
|
|
64
|
+
this.currentActor = actor !== null && actor !== void 0 ? actor : undefined;
|
|
65
|
+
if (actor) {
|
|
66
|
+
this.analytics.setActor(actor);
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
|
-
return this.
|
|
69
|
+
return this.currentActor;
|
|
73
70
|
}
|
|
74
71
|
/**
|
|
75
72
|
* Ensure that there is a logged-in actor. Show a login prompt if not.
|