eas-cli 19.0.8 → 20.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.
Files changed (48) hide show
  1. package/README.md +305 -101
  2. package/build/build/createContext.d.ts +2 -1
  3. package/build/build/createContext.js +3 -1
  4. package/build/build/ios/credentials.js +5 -1
  5. package/build/build/ios/prepareJob.js +3 -0
  6. package/build/build/runBuildAndSubmit.d.ts +1 -0
  7. package/build/build/runBuildAndSubmit.js +1 -0
  8. package/build/build/types.d.ts +1 -0
  9. package/build/commands/build/index.d.ts +1 -0
  10. package/build/commands/build/index.js +13 -0
  11. package/build/commands/build/internal.d.ts +1 -0
  12. package/build/commands/build/internal.js +5 -0
  13. package/build/commands/go.d.ts +1 -0
  14. package/build/commands/go.js +29 -1
  15. package/build/commands/observe/events.d.ts +3 -3
  16. package/build/commands/observe/events.js +69 -51
  17. package/build/commands/observe/{logs.d.ts → metrics-summary.d.ts} +3 -11
  18. package/build/commands/observe/metrics-summary.js +95 -0
  19. package/build/commands/observe/metrics.d.ts +8 -3
  20. package/build/commands/observe/metrics.js +63 -47
  21. package/build/commands/observe/routes.d.ts +0 -1
  22. package/build/commands/observe/routes.js +0 -4
  23. package/build/commands/observe/versions.d.ts +0 -1
  24. package/build/commands/observe/versions.js +0 -4
  25. package/build/commands/update/embedded/upload.d.ts +20 -0
  26. package/build/commands/update/embedded/upload.js +129 -0
  27. package/build/credentials/context.d.ts +2 -0
  28. package/build/credentials/context.js +2 -0
  29. package/build/credentials/ios/actions/DeviceUtils.d.ts +2 -0
  30. package/build/credentials/ios/actions/DeviceUtils.js +21 -0
  31. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.d.ts +1 -0
  32. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +76 -14
  33. package/build/credentials/ios/actions/SetUpTargetBuildCredentials.js +8 -0
  34. package/build/graphql/client.js +1 -0
  35. package/build/graphql/generated.d.ts +70 -1
  36. package/build/graphql/mutations/EmbeddedUpdateAssetMutation.d.ts +13 -0
  37. package/build/graphql/mutations/EmbeddedUpdateAssetMutation.js +32 -0
  38. package/build/graphql/mutations/EmbeddedUpdateMutation.d.ts +14 -0
  39. package/build/graphql/mutations/EmbeddedUpdateMutation.js +37 -0
  40. package/build/graphql/queries/WorkflowRunQuery.d.ts +2 -1
  41. package/build/graphql/queries/WorkflowRunQuery.js +19 -6
  42. package/build/observe/formatCustomEvents.js +5 -5
  43. package/build/observe/metricNames.js +2 -0
  44. package/build/update/embeddedManifest.d.ts +3 -0
  45. package/build/update/embeddedManifest.js +28 -0
  46. package/oclif.manifest.json +1852 -1714
  47. package/package.json +6 -6
  48. package/build/commands/observe/logs.js +0 -141
@@ -9,7 +9,7 @@ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGr
9
9
  import { CustomBuildConfigMetadata } from '../project/customBuildConfig';
10
10
  import { Actor } from '../user/User';
11
11
  import { Client } from '../vcs/vcs';
12
- export declare function createBuildContextAsync<T extends Platform>({ buildProfileName, buildProfile, easJsonCliConfig, clearCache, localBuildOptions, nonInteractive, noWait, platform, projectDir, resourceClassFlag, message, actor, graphqlClient, analytics, vcsClient, getDynamicPrivateProjectConfigAsync, customBuildConfigMetadata, buildLoggerLevel, freezeCredentials, isVerboseLoggingEnabled, whatToTest, env, }: {
12
+ export declare function createBuildContextAsync<T extends Platform>({ buildProfileName, buildProfile, easJsonCliConfig, clearCache, localBuildOptions, nonInteractive, noWait, platform, projectDir, resourceClassFlag, message, actor, graphqlClient, analytics, vcsClient, getDynamicPrivateProjectConfigAsync, customBuildConfigMetadata, buildLoggerLevel, freezeCredentials, refreshAdHocProvisioningProfile: refreshAdHocProvisioningProfileFlag, isVerboseLoggingEnabled, whatToTest, env, }: {
13
13
  buildProfileName: string;
14
14
  buildProfile: BuildProfile<T>;
15
15
  easJsonCliConfig: EasJson['cli'];
@@ -29,6 +29,7 @@ export declare function createBuildContextAsync<T extends Platform>({ buildProfi
29
29
  customBuildConfigMetadata?: CustomBuildConfigMetadata;
30
30
  buildLoggerLevel?: LoggerLevel;
31
31
  freezeCredentials: boolean;
32
+ refreshAdHocProvisioningProfile?: boolean;
32
33
  isVerboseLoggingEnabled: boolean;
33
34
  whatToTest?: string;
34
35
  env: Record<string, string>;
@@ -16,7 +16,7 @@ const AnalyticsManager_1 = require("../analytics/AnalyticsManager");
16
16
  const context_1 = require("../credentials/context");
17
17
  const projectUtils_1 = require("../project/projectUtils");
18
18
  const workflow_1 = require("../project/workflow");
19
- async function createBuildContextAsync({ buildProfileName, buildProfile, easJsonCliConfig, clearCache = false, localBuildOptions, nonInteractive, noWait, platform, projectDir, resourceClassFlag, message, actor, graphqlClient, analytics, vcsClient, getDynamicPrivateProjectConfigAsync, customBuildConfigMetadata, buildLoggerLevel, freezeCredentials, isVerboseLoggingEnabled, whatToTest, env, }) {
19
+ async function createBuildContextAsync({ buildProfileName, buildProfile, easJsonCliConfig, clearCache = false, localBuildOptions, nonInteractive, noWait, platform, projectDir, resourceClassFlag, message, actor, graphqlClient, analytics, vcsClient, getDynamicPrivateProjectConfigAsync, customBuildConfigMetadata, buildLoggerLevel, freezeCredentials, refreshAdHocProvisioningProfile: refreshAdHocProvisioningProfileFlag, isVerboseLoggingEnabled, whatToTest, env, }) {
20
20
  const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({
21
21
  env,
22
22
  });
@@ -33,6 +33,7 @@ async function createBuildContextAsync({ buildProfileName, buildProfile, easJson
33
33
  : buildProfile?.buildConfiguration === 'Debug') ??
34
34
  false;
35
35
  const requiredPackageManager = (0, package_manager_1.resolvePackageManager)(projectDir);
36
+ const refreshAdHocProvisioningProfile = refreshAdHocProvisioningProfileFlag ?? false;
36
37
  const credentialsCtx = new context_1.CredentialsContext({
37
38
  projectInfo: { exp, projectId },
38
39
  nonInteractive,
@@ -44,6 +45,7 @@ async function createBuildContextAsync({ buildProfileName, buildProfile, easJson
44
45
  easJsonCliConfig,
45
46
  vcsClient,
46
47
  freezeCredentials,
48
+ refreshAdHocProvisioningProfile,
47
49
  });
48
50
  const devClientProperties = getDevClientEventProperties({
49
51
  platform,
@@ -11,13 +11,17 @@ async function ensureIosCredentialsAsync(buildCtx, targets) {
11
11
  if (!shouldProvideCredentials(buildCtx)) {
12
12
  return;
13
13
  }
14
+ const { credentialsSource } = buildCtx.buildProfile;
15
+ if (buildCtx.credentialsCtx.refreshAdHocProvisioningProfile &&
16
+ credentialsSource === 'local') {
17
+ throw new Error('--refresh-ad-hoc-provisioning-profile cannot be used with credentialsSource "local". Use remote credentials or omit the flag.');
18
+ }
14
19
  const provider = new IosCredentialsProvider_1.default(buildCtx.credentialsCtx, {
15
20
  app: await (0, BuildCredentialsUtils_1.getAppFromContextAsync)(buildCtx.credentialsCtx),
16
21
  targets,
17
22
  distribution: buildCtx.buildProfile.distribution ?? 'store',
18
23
  enterpriseProvisioning: buildCtx.buildProfile.enterpriseProvisioning,
19
24
  });
20
- const { credentialsSource } = buildCtx.buildProfile;
21
25
  (0, credentials_1.logCredentialsSource)(credentialsSource, eas_build_job_1.Platform.IOS);
22
26
  return {
23
27
  credentials: await provider.getCredentialsAsync(credentialsSource),
@@ -91,6 +91,9 @@ async function prepareJobAsync(ctx, jobData) {
91
91
  // See: https://github.com/expo/eas-build/pull/454
92
92
  appId: ctx.projectId,
93
93
  initiatingUserId: ctx.user.id,
94
+ ...(ctx.credentialsCtx.refreshAdHocProvisioningProfile && {
95
+ refreshAdHocProvisioningProfile: true,
96
+ }),
94
97
  };
95
98
  return (0, eas_build_job_1.sanitizeBuildJob)(job);
96
99
  }
@@ -25,6 +25,7 @@ export interface BuildFlags {
25
25
  message?: string;
26
26
  buildLoggerLevel?: LoggerLevel;
27
27
  freezeCredentials: boolean;
28
+ refreshAdHocProvisioningProfile?: boolean;
28
29
  isVerboseLoggingEnabled?: boolean;
29
30
  whatToTest?: string;
30
31
  simulator?: SimulatorRunTarget;
@@ -243,6 +243,7 @@ async function prepareAndStartBuildAsync({ projectDir, flags, moreBuilds, buildP
243
243
  customBuildConfigMetadata,
244
244
  buildLoggerLevel: flags.buildLoggerLevel ?? (log_1.default.isDebug ? logger_1.LoggerLevel.DEBUG : undefined),
245
245
  freezeCredentials: flags.freezeCredentials,
246
+ refreshAdHocProvisioningProfile: flags.refreshAdHocProvisioningProfile,
246
247
  isVerboseLoggingEnabled: flags.isVerboseLoggingEnabled ?? false,
247
248
  whatToTest: flags.whatToTest,
248
249
  env,
@@ -31,4 +31,5 @@ export interface BuildFlags {
31
31
  message?: string;
32
32
  buildLoggerLevel?: LoggerLevel;
33
33
  freezeCredentials: boolean;
34
+ refreshAdHocProvisioningProfile?: boolean;
34
35
  }
@@ -21,6 +21,7 @@ export default class Build extends EasCommand {
21
21
  message: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
22
  'build-logger-level': import("@oclif/core/lib/interfaces").OptionFlag<LoggerLevel | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
23
23
  'freeze-credentials': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
+ 'refresh-ad-hoc-provisioning-profile': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
25
  'verbose-logs': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
26
  };
26
27
  static contextDefinition: {
@@ -92,6 +92,10 @@ class Build extends EasCommand_1.default {
92
92
  default: false,
93
93
  description: 'Prevent the build from updating credentials in non-interactive mode',
94
94
  }),
95
+ 'refresh-ad-hoc-provisioning-profile': core_1.Flags.boolean({
96
+ default: false,
97
+ description: 'Refresh managed ad-hoc provisioning profiles from App Store Connect before gathering build credentials',
98
+ }),
95
99
  'verbose-logs': core_1.Flags.boolean({
96
100
  default: false,
97
101
  description: 'Use verbose logs for the build process',
@@ -138,6 +142,14 @@ class Build extends EasCommand_1.default {
138
142
  }
139
143
  sanitizeFlags(flags) {
140
144
  const { json, nonInteractive } = (0, flags_1.resolveNonInteractiveAndJsonFlags)(flags);
145
+ if (flags['refresh-ad-hoc-provisioning-profile']) {
146
+ if (!nonInteractive) {
147
+ core_1.Errors.error('--refresh-ad-hoc-provisioning-profile can only be used in non-interactive mode.', { exit: 1 });
148
+ }
149
+ if (flags['freeze-credentials']) {
150
+ core_1.Errors.error('Cannot use --refresh-ad-hoc-provisioning-profile with --freeze-credentials.', { exit: 1 });
151
+ }
152
+ }
141
153
  if (!flags.local && flags.output) {
142
154
  core_1.Errors.error('--output is allowed only for local builds', { exit: 1 });
143
155
  }
@@ -185,6 +197,7 @@ class Build extends EasCommand_1.default {
185
197
  message,
186
198
  buildLoggerLevel: flags['build-logger-level'],
187
199
  freezeCredentials: flags['freeze-credentials'],
200
+ refreshAdHocProvisioningProfile: flags['refresh-ad-hoc-provisioning-profile'],
188
201
  isVerboseLoggingEnabled: flags['verbose-logs'],
189
202
  whatToTest: flags['what-to-test'],
190
203
  };
@@ -12,6 +12,7 @@ export default class BuildInternal extends EasCommand {
12
12
  profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
13
  'auto-submit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
14
  'auto-submit-with-profile': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ 'refresh-ad-hoc-provisioning-profile': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
16
  };
16
17
  static contextDefinition: {
17
18
  vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
@@ -37,6 +37,10 @@ class BuildInternal extends EasCommand_1.default {
37
37
  helpValue: 'PROFILE_NAME',
38
38
  exclusive: ['auto-submit'],
39
39
  }),
40
+ 'refresh-ad-hoc-provisioning-profile': core_1.Flags.boolean({
41
+ default: false,
42
+ description: 'Refresh managed ad-hoc provisioning profiles from App Store Connect before gathering build credentials',
43
+ }),
40
44
  };
41
45
  static contextDefinition = {
42
46
  ...this.ContextOptions.LoggedIn,
@@ -70,6 +74,7 @@ class BuildInternal extends EasCommand_1.default {
70
74
  profile: flags.profile,
71
75
  nonInteractive: true,
72
76
  freezeCredentials: false,
77
+ refreshAdHocProvisioningProfile: flags['refresh-ad-hoc-provisioning-profile'],
73
78
  wait: false,
74
79
  clearCache: false,
75
80
  json: true,
@@ -14,6 +14,7 @@ export default class Go extends EasCommand {
14
14
  loggedIn: import("../commandUtils/context/LoggedInContextField").default;
15
15
  };
16
16
  runAsync(): Promise<void>;
17
+ private selectSdkVersionAsync;
17
18
  private generateBundleId;
18
19
  private ensureEasProjectAsync;
19
20
  private setupCredentialsAsync;
@@ -169,7 +169,10 @@ class Go extends EasCommand_1.default {
169
169
  if (detectedSdkVersion && !flags['sdk-version']) {
170
170
  log_1.default.log(`Current project using SDK ${detectedSdkVersion.split('.')[0]}. Auto-selected same version. To use a different version, pass --sdk-version.`);
171
171
  }
172
- const sdkVersion = flags['sdk-version'] ?? detectedSdkVersion;
172
+ let sdkVersion = flags['sdk-version'] ?? detectedSdkVersion;
173
+ if (!sdkVersion) {
174
+ ({ sdkVersion } = await this.selectSdkVersionAsync(graphqlClient));
175
+ }
173
176
  const bundleId = flags['bundle-id'] ?? this.generateBundleId(actor);
174
177
  if (!(0, bundleIdentifier_1.isBundleIdentifierValid)(bundleId)) {
175
178
  throw new Error(`"${bundleId}" is not a valid iOS bundle identifier. ${bundleIdentifier_1.INVALID_BUNDLE_IDENTIFIER_MESSAGE} Pass a valid identifier with --bundle-id.`);
@@ -217,6 +220,31 @@ class Go extends EasCommand_1.default {
217
220
  await fs.remove(tmpDir);
218
221
  }
219
222
  }
223
+ async selectSdkVersionAsync(graphqlClient) {
224
+ let versions;
225
+ try {
226
+ versions = await WorkflowRunQuery_1.WorkflowRunQuery.expoGoSupportedSdkVersionsAsync(graphqlClient);
227
+ }
228
+ catch {
229
+ return { sdkVersion: undefined };
230
+ }
231
+ const selectable = versions.filter(v => !v.isDeprecated);
232
+ if (selectable.length === 0) {
233
+ return { sdkVersion: undefined };
234
+ }
235
+ const defaultVersion = selectable.find(v => v.isLatest) ?? selectable.at(-1);
236
+ return {
237
+ sdkVersion: await (0, prompts_1.selectAsync)('Select an Expo SDK version', selectable.map(v => {
238
+ const major = v.sdkVersion.split('.')[0];
239
+ const title = v.isLatest
240
+ ? `SDK ${major} (latest)`
241
+ : v.isBeta
242
+ ? `SDK ${major} (beta)`
243
+ : `SDK ${major}`;
244
+ return { title, value: v.sdkVersion };
245
+ }), { initial: defaultVersion?.sdkVersion }),
246
+ };
247
+ }
220
248
  generateBundleId(actor) {
221
249
  const username = (0, actions_1.ensureActorHasPrimaryAccount)(actor).name;
222
250
  const sanitizedUsername = username
@@ -1,14 +1,15 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export default class ObserveEvents extends EasCommand {
3
- static hidden: boolean;
4
3
  static description: string;
5
4
  static args: {
6
- metric: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ eventName: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
6
  };
8
7
  static flags: {
9
8
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
9
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
10
  'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'session-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'all-events': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
13
  'update-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
14
  'app-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
15
  start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -17,7 +18,6 @@ export default class ObserveEvents extends EasCommand {
17
18
  limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined>;
18
19
  after: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
20
  platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
- sort: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
21
21
  };
22
22
  static contextDefinition: {
23
23
  loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
@@ -3,37 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const core_1 = require("@oclif/core");
5
5
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
6
- const errors_1 = require("../../commandUtils/errors");
7
6
  const flags_1 = require("../../commandUtils/flags");
8
7
  const pagination_1 = require("../../commandUtils/pagination");
9
8
  const log_1 = tslib_1.__importDefault(require("../../log"));
10
- const fetchEvents_1 = require("../../observe/fetchEvents");
9
+ const ObserveQuery_1 = require("../../graphql/queries/ObserveQuery");
10
+ const fetchCustomEvents_1 = require("../../observe/fetchCustomEvents");
11
11
  const flags_2 = require("../../observe/flags");
12
- const metricNames_1 = require("../../observe/metricNames");
13
- const formatEvents_1 = require("../../observe/formatEvents");
12
+ const formatCustomEvents_1 = require("../../observe/formatCustomEvents");
14
13
  const platforms_1 = require("../../observe/platforms");
15
14
  const resolveProjectContext_1 = require("../../observe/resolveProjectContext");
16
15
  const startAndEndTime_1 = require("../../observe/startAndEndTime");
17
- const prompts_1 = require("../../prompts");
18
16
  const json_1 = require("../../utils/json");
19
17
  const DEFAULT_EVENTS_LIMIT = 10;
20
18
  class ObserveEvents extends EasCommand_1.default {
21
- static hidden = true;
22
- static description = 'display individual app performance events ordered by metric value';
19
+ static description = 'display individual events emitted by the app via `logEvent`, filtered by the event name in the argument. With no arguments, a list of the available event names and associated event counts is returned.';
23
20
  static args = {
24
- metric: core_1.Args.string({
25
- description: 'Metric to query (e.g. tti, cold_launch)',
21
+ eventName: core_1.Args.string({
22
+ description: 'Event name to filter by',
26
23
  required: false,
27
- options: Object.keys(metricNames_1.METRIC_ALIASES),
28
24
  }),
29
25
  };
30
26
  static flags = {
31
- sort: core_1.Flags.option({
32
- description: 'Sort order for events',
33
- options: Object.values(fetchEvents_1.EventsOrderPreset).map(s => s.toLowerCase()),
34
- required: false,
35
- default: fetchEvents_1.EventsOrderPreset.Oldest.valueOf().toLowerCase(),
36
- })(),
37
27
  ...flags_2.ObservePlatformFlag,
38
28
  ...flags_2.ObserveAfterFlag,
39
29
  limit: (0, pagination_1.getLimitFlagWithCustomValues)({
@@ -43,6 +33,13 @@ class ObserveEvents extends EasCommand_1.default {
43
33
  ...flags_2.ObserveTimeRangeFlags,
44
34
  ...flags_2.ObserveAppVersionFlag,
45
35
  ...flags_2.ObserveUpdateIdFlag,
36
+ 'session-id': core_1.Flags.string({
37
+ description: 'Filter by session ID',
38
+ }),
39
+ 'all-events': core_1.Flags.boolean({
40
+ description: 'When no event name argument is provided, list all events across all event names instead of a summary of event names + counts.',
41
+ default: false,
42
+ }),
46
43
  ...flags_2.ObserveProjectIdFlag,
47
44
  ...flags_1.EasNonInteractiveAndJsonFlags,
48
45
  };
@@ -55,6 +52,9 @@ class ObserveEvents extends EasCommand_1.default {
55
52
  };
56
53
  async runAsync() {
57
54
  const { flags, args } = await this.parse(ObserveEvents);
55
+ if (args.eventName && flags['all-events']) {
56
+ throw new Error('--all-events cannot be combined with an event name argument. Pass an event name to filter by it, or pass --all-events to list all events across all event names.');
57
+ }
58
58
  const { projectId, graphqlClient } = await (0, resolveProjectContext_1.resolveObserveCommandContextAsync)({
59
59
  command: this,
60
60
  commandClass: ObserveEvents,
@@ -65,53 +65,71 @@ class ObserveEvents extends EasCommand_1.default {
65
65
  if (flags.json) {
66
66
  (0, json_1.enableJsonOutput)();
67
67
  }
68
- else {
69
- log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
70
- }
71
- let metricName;
72
- if (args.metric) {
73
- metricName = (0, metricNames_1.resolveMetricName)(args.metric);
74
- }
75
- else if (flags['non-interactive']) {
76
- throw new errors_1.EasCommandError('A metric argument is required in non-interactive mode. Available metrics: ' +
77
- Object.keys(metricNames_1.METRIC_ALIASES).join(', '));
78
- }
79
- else {
80
- const choices = Object.entries(metricNames_1.METRIC_SHORT_NAMES).map(([fullName, displayName]) => ({
81
- title: `${displayName} (${fullName})`,
82
- value: fullName,
83
- }));
84
- metricName = await (0, prompts_1.selectAsync)('Select a metric', choices);
85
- }
86
- const orderBy = (0, fetchEvents_1.resolveOrderBy)(flags.sort);
87
68
  const { daysBack, startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
88
69
  const platform = (0, platforms_1.appObservePlatformFromFlag)(flags.platform);
89
- const platforms = (0, platforms_1.appPlatformsFromFlag)(flags.platform);
90
- const [{ events, pageInfo }, totalEventCount] = await Promise.all([
91
- (0, fetchEvents_1.fetchObserveEventsAsync)(graphqlClient, projectId, {
92
- metricName,
93
- orderBy,
94
- limit: flags.limit ?? DEFAULT_EVENTS_LIMIT,
95
- ...(flags.after && { after: flags.after }),
70
+ if (!args.eventName && !flags['all-events']) {
71
+ const { names, isTruncated } = await ObserveQuery_1.ObserveQuery.customEventNamesAsync(graphqlClient, {
72
+ appId: projectId,
73
+ startTime,
74
+ endTime,
75
+ platform,
76
+ });
77
+ if (flags.json) {
78
+ (0, json_1.printJsonOnlyOutput)((0, formatCustomEvents_1.buildObserveCustomEventNamesJson)(names, isTruncated));
79
+ }
80
+ else {
81
+ log_1.default.addNewLineIfNone();
82
+ log_1.default.log((0, formatCustomEvents_1.buildObserveCustomEventNamesTable)(names, {
83
+ daysBack,
84
+ startTime,
85
+ endTime,
86
+ isTruncated,
87
+ }));
88
+ }
89
+ return;
90
+ }
91
+ const { events, pageInfo } = await (0, fetchCustomEvents_1.fetchObserveCustomEventsAsync)(graphqlClient, projectId, {
92
+ eventName: args.eventName,
93
+ limit: flags.limit ?? DEFAULT_EVENTS_LIMIT,
94
+ ...(flags.after && { after: flags.after }),
95
+ startTime,
96
+ endTime,
97
+ platform,
98
+ appVersion: flags['app-version'],
99
+ updateId: flags['update-id'],
100
+ sessionId: flags['session-id'],
101
+ });
102
+ if (args.eventName && events.length === 0) {
103
+ const { names, isTruncated } = await ObserveQuery_1.ObserveQuery.customEventNamesAsync(graphqlClient, {
104
+ appId: projectId,
96
105
  startTime,
97
106
  endTime,
98
107
  platform,
99
- appVersion: flags['app-version'],
100
- updateId: flags['update-id'],
101
- }),
102
- (0, fetchEvents_1.fetchTotalEventCountAsync)(graphqlClient, projectId, metricName, platforms, startTime, endTime),
103
- ]);
108
+ });
109
+ if (flags.json) {
110
+ (0, json_1.printJsonOnlyOutput)((0, formatCustomEvents_1.buildObserveCustomEventsEmptyWithSuggestionsJson)(args.eventName, names, isTruncated));
111
+ }
112
+ else {
113
+ log_1.default.addNewLineIfNone();
114
+ log_1.default.log((0, formatCustomEvents_1.buildObserveCustomEventsEmptyWithSuggestionsTable)(args.eventName, names, {
115
+ daysBack,
116
+ startTime,
117
+ endTime,
118
+ isTruncated,
119
+ }));
120
+ }
121
+ return;
122
+ }
104
123
  if (flags.json) {
105
- (0, json_1.printJsonOnlyOutput)((0, formatEvents_1.buildObserveEventsJson)(events, pageInfo));
124
+ (0, json_1.printJsonOnlyOutput)((0, formatCustomEvents_1.buildObserveCustomEventsJson)(events, pageInfo));
106
125
  }
107
126
  else {
108
127
  log_1.default.addNewLineIfNone();
109
- log_1.default.log((0, formatEvents_1.buildObserveEventsTable)(events, pageInfo, {
110
- metricName,
128
+ log_1.default.log((0, formatCustomEvents_1.buildObserveCustomEventsTable)(events, pageInfo, {
129
+ eventName: args.eventName,
111
130
  daysBack,
112
131
  startTime,
113
132
  endTime,
114
- totalEventCount,
115
133
  }));
116
134
  }
117
135
  }
@@ -1,23 +1,15 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
- export default class ObserveLogs extends EasCommand {
3
- static hidden: boolean;
2
+ export default class ObserveMetricsSummary extends EasCommand {
4
3
  static description: string;
5
- static args: {
6
- eventName: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
- };
8
4
  static flags: {
9
5
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
6
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
7
  'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- 'session-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
- 'all-events': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
- 'update-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
- 'app-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
8
  start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
9
  end: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
10
  days: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
- limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined>;
20
- after: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ metric: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ stat: import("@oclif/core/lib/interfaces").OptionFlag<("min" | "max" | "median" | "average" | "p80" | "p90" | "p99" | "eventCount")[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
21
13
  platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
14
  };
23
15
  static contextDefinition: {
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
5
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
6
+ const flags_1 = require("../../commandUtils/flags");
7
+ const log_1 = tslib_1.__importDefault(require("../../log"));
8
+ const fetchMetrics_1 = require("../../observe/fetchMetrics");
9
+ const flags_2 = require("../../observe/flags");
10
+ const formatMetrics_1 = require("../../observe/formatMetrics");
11
+ const metricNames_1 = require("../../observe/metricNames");
12
+ const platforms_1 = require("../../observe/platforms");
13
+ const resolveProjectContext_1 = require("../../observe/resolveProjectContext");
14
+ const startAndEndTime_1 = require("../../observe/startAndEndTime");
15
+ const json_1 = require("../../utils/json");
16
+ const DEFAULT_METRICS = [
17
+ 'expo.app_startup.cold_launch_time',
18
+ 'expo.app_startup.warm_launch_time',
19
+ 'expo.app_startup.tti',
20
+ 'expo.app_startup.ttr',
21
+ 'expo.app_startup.bundle_load_time',
22
+ ];
23
+ const DEFAULT_STATS_TABLE = ['median', 'eventCount'];
24
+ const DEFAULT_STATS_JSON = [
25
+ 'min',
26
+ 'median',
27
+ 'max',
28
+ 'average',
29
+ 'p80',
30
+ 'p90',
31
+ 'p99',
32
+ 'eventCount',
33
+ ];
34
+ class ObserveMetricsSummary extends EasCommand_1.default {
35
+ static description = 'display aggregated performance metric statistics grouped by app version';
36
+ static flags = {
37
+ ...flags_2.ObservePlatformFlag,
38
+ metric: core_1.Flags.option({
39
+ description: 'Metric name to display (can be specified multiple times).',
40
+ multiple: true,
41
+ options: Object.keys(metricNames_1.METRIC_ALIASES),
42
+ })(),
43
+ stat: core_1.Flags.option({
44
+ description: 'Statistic to display per metric (can be specified multiple times)',
45
+ multiple: true,
46
+ options: DEFAULT_STATS_JSON,
47
+ })(),
48
+ ...flags_2.ObserveTimeRangeFlags,
49
+ ...flags_2.ObserveProjectIdFlag,
50
+ ...flags_1.EasNonInteractiveAndJsonFlags,
51
+ };
52
+ static contextDefinition = {
53
+ ...this.ContextOptions.ProjectId,
54
+ ...this.ContextOptions.LoggedIn,
55
+ };
56
+ static loggedInOnlyContextDefinition = {
57
+ ...this.ContextOptions.LoggedIn,
58
+ };
59
+ async runAsync() {
60
+ const { flags } = await this.parse(ObserveMetricsSummary);
61
+ const { projectId, graphqlClient } = await (0, resolveProjectContext_1.resolveObserveCommandContextAsync)({
62
+ command: this,
63
+ commandClass: ObserveMetricsSummary,
64
+ loggedInOnlyContextDefinition: ObserveMetricsSummary.loggedInOnlyContextDefinition,
65
+ projectIdOverride: flags['project-id'],
66
+ nonInteractive: flags['non-interactive'],
67
+ });
68
+ if (flags.json) {
69
+ (0, json_1.enableJsonOutput)();
70
+ }
71
+ const metricNames = flags.metric?.length
72
+ ? flags.metric.map(metricNames_1.resolveMetricName)
73
+ : DEFAULT_METRICS;
74
+ const { daysBack, startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
75
+ const platforms = (0, platforms_1.appPlatformsFromFlag)(flags.platform);
76
+ const { metricsMap, buildNumbersMap, updateIdsMap, totalEventCounts } = await (0, fetchMetrics_1.fetchObserveMetricsAsync)(graphqlClient, projectId, metricNames, platforms, startTime, endTime);
77
+ const argumentsStat = flags.stat?.length
78
+ ? Array.from(new Set(flags.stat.map(formatMetrics_1.resolveStatKey)))
79
+ : undefined;
80
+ if (flags.json) {
81
+ const stats = argumentsStat ?? DEFAULT_STATS_JSON;
82
+ (0, json_1.printJsonOnlyOutput)((0, formatMetrics_1.buildObserveMetricsJson)(metricsMap, metricNames, stats, totalEventCounts, buildNumbersMap, updateIdsMap));
83
+ }
84
+ else {
85
+ const stats = argumentsStat ?? DEFAULT_STATS_TABLE;
86
+ log_1.default.addNewLineIfNone();
87
+ log_1.default.log((0, formatMetrics_1.buildObserveMetricsTable)(metricsMap, metricNames, stats, {
88
+ daysBack,
89
+ buildNumbersMap,
90
+ totalEventCounts,
91
+ }));
92
+ }
93
+ }
94
+ }
95
+ exports.default = ObserveMetricsSummary;
@@ -1,17 +1,22 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export default class ObserveMetrics extends EasCommand {
3
- static hidden: boolean;
4
3
  static description: string;
4
+ static args: {
5
+ metric: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
5
7
  static flags: {
6
8
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
9
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
10
  'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'update-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'app-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
13
  start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
14
  end: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
15
  days: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- metric: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
- stat: import("@oclif/core/lib/interfaces").OptionFlag<("min" | "max" | "median" | "average" | "p80" | "p90" | "p99" | "eventCount")[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined>;
17
+ after: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
18
  platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ sort: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
15
20
  };
16
21
  static contextDefinition: {
17
22
  loggedIn: import("../../commandUtils/context/LoggedInContextField").default;