eas-cli 19.1.0 → 20.1.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 (51) hide show
  1. package/README.md +371 -100
  2. package/build/commands/go.d.ts +1 -0
  3. package/build/commands/go.js +29 -1
  4. package/build/commands/observe/events.d.ts +3 -3
  5. package/build/commands/observe/events.js +69 -51
  6. package/build/commands/observe/{logs.d.ts → metrics-summary.d.ts} +3 -11
  7. package/build/commands/observe/metrics-summary.js +95 -0
  8. package/build/commands/observe/metrics.d.ts +8 -3
  9. package/build/commands/observe/metrics.js +63 -47
  10. package/build/commands/observe/routes.d.ts +0 -1
  11. package/build/commands/observe/routes.js +0 -4
  12. package/build/commands/observe/versions.d.ts +0 -1
  13. package/build/commands/observe/versions.js +0 -4
  14. package/build/commands/simulator/exec.d.ts +12 -0
  15. package/build/commands/simulator/exec.js +42 -0
  16. package/build/commands/simulator/get.d.ts +2 -1
  17. package/build/commands/simulator/get.js +13 -7
  18. package/build/commands/simulator/start.d.ts +3 -0
  19. package/build/commands/simulator/start.js +65 -5
  20. package/build/commands/simulator/stop.d.ts +2 -1
  21. package/build/commands/simulator/stop.js +16 -9
  22. package/build/commands/update/embedded/delete.d.ts +15 -0
  23. package/build/commands/update/embedded/delete.js +55 -0
  24. package/build/commands/update/embedded/list.d.ts +19 -0
  25. package/build/commands/update/embedded/list.js +132 -0
  26. package/build/commands/update/embedded/upload.d.ts +20 -0
  27. package/build/commands/update/embedded/upload.js +129 -0
  28. package/build/commands/update/embedded/view.d.ts +17 -0
  29. package/build/commands/update/embedded/view.js +75 -0
  30. package/build/graphql/client.js +1 -0
  31. package/build/graphql/generated.d.ts +434 -4
  32. package/build/graphql/generated.js +35 -1
  33. package/build/graphql/mutations/EmbeddedUpdateAssetMutation.d.ts +13 -0
  34. package/build/graphql/mutations/EmbeddedUpdateAssetMutation.js +32 -0
  35. package/build/graphql/mutations/EmbeddedUpdateMutation.d.ts +19 -0
  36. package/build/graphql/mutations/EmbeddedUpdateMutation.js +51 -0
  37. package/build/graphql/queries/EmbeddedUpdateQuery.d.ts +18 -0
  38. package/build/graphql/queries/EmbeddedUpdateQuery.js +81 -0
  39. package/build/graphql/queries/WorkflowRunQuery.d.ts +2 -1
  40. package/build/graphql/queries/WorkflowRunQuery.js +19 -6
  41. package/build/observe/formatCustomEvents.js +5 -5
  42. package/build/observe/metricNames.js +2 -0
  43. package/build/simulator/env.d.ts +7 -0
  44. package/build/simulator/env.js +44 -0
  45. package/build/simulator/utils.d.ts +3 -1
  46. package/build/simulator/utils.js +26 -7
  47. package/build/update/embeddedManifest.d.ts +3 -0
  48. package/build/update/embeddedManifest.js +28 -0
  49. package/oclif.manifest.json +2803 -2309
  50. package/package.json +6 -6
  51. package/build/commands/observe/logs.js +0 -141
@@ -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;
@@ -3,50 +3,45 @@ 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");
6
7
  const flags_1 = require("../../commandUtils/flags");
8
+ const pagination_1 = require("../../commandUtils/pagination");
7
9
  const log_1 = tslib_1.__importDefault(require("../../log"));
8
- const fetchMetrics_1 = require("../../observe/fetchMetrics");
10
+ const fetchEvents_1 = require("../../observe/fetchEvents");
9
11
  const flags_2 = require("../../observe/flags");
10
- const formatMetrics_1 = require("../../observe/formatMetrics");
11
12
  const metricNames_1 = require("../../observe/metricNames");
13
+ const formatEvents_1 = require("../../observe/formatEvents");
12
14
  const platforms_1 = require("../../observe/platforms");
13
15
  const resolveProjectContext_1 = require("../../observe/resolveProjectContext");
14
16
  const startAndEndTime_1 = require("../../observe/startAndEndTime");
17
+ const prompts_1 = require("../../prompts");
15
18
  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
- ];
19
+ const DEFAULT_EVENTS_LIMIT = 10;
34
20
  class ObserveMetrics extends EasCommand_1.default {
35
- static hidden = true;
36
- static description = 'display app performance metrics grouped by app version';
37
- static flags = {
38
- ...flags_2.ObservePlatformFlag,
39
- metric: core_1.Flags.option({
40
- description: 'Metric name to display (can be specified multiple times).',
41
- multiple: true,
21
+ static description = 'display individual performance metric samples ordered by value';
22
+ static args = {
23
+ metric: core_1.Args.string({
24
+ description: 'Metric to query (e.g. tti, cold_launch)',
25
+ required: false,
42
26
  options: Object.keys(metricNames_1.METRIC_ALIASES),
27
+ }),
28
+ };
29
+ static flags = {
30
+ sort: core_1.Flags.option({
31
+ description: 'Sort order for events',
32
+ options: Object.values(fetchEvents_1.EventsOrderPreset).map(s => s.toLowerCase()),
33
+ required: false,
34
+ default: fetchEvents_1.EventsOrderPreset.Oldest.valueOf().toLowerCase(),
43
35
  })(),
44
- stat: core_1.Flags.option({
45
- description: 'Statistic to display per metric (can be specified multiple times)',
46
- multiple: true,
47
- options: DEFAULT_STATS_JSON,
48
- })(),
36
+ ...flags_2.ObservePlatformFlag,
37
+ ...flags_2.ObserveAfterFlag,
38
+ limit: (0, pagination_1.getLimitFlagWithCustomValues)({
39
+ defaultTo: DEFAULT_EVENTS_LIMIT,
40
+ limit: 100,
41
+ }),
49
42
  ...flags_2.ObserveTimeRangeFlags,
43
+ ...flags_2.ObserveAppVersionFlag,
44
+ ...flags_2.ObserveUpdateIdFlag,
50
45
  ...flags_2.ObserveProjectIdFlag,
51
46
  ...flags_1.EasNonInteractiveAndJsonFlags,
52
47
  };
@@ -58,7 +53,7 @@ class ObserveMetrics extends EasCommand_1.default {
58
53
  ...this.ContextOptions.LoggedIn,
59
54
  };
60
55
  async runAsync() {
61
- const { flags } = await this.parse(ObserveMetrics);
56
+ const { flags, args } = await this.parse(ObserveMetrics);
62
57
  const { projectId, graphqlClient } = await (0, resolveProjectContext_1.resolveObserveCommandContextAsync)({
63
58
  command: this,
64
59
  commandClass: ObserveMetrics,
@@ -69,29 +64,50 @@ class ObserveMetrics extends EasCommand_1.default {
69
64
  if (flags.json) {
70
65
  (0, json_1.enableJsonOutput)();
71
66
  }
67
+ let metricName;
68
+ if (args.metric) {
69
+ metricName = (0, metricNames_1.resolveMetricName)(args.metric);
70
+ }
71
+ else if (flags['non-interactive']) {
72
+ throw new errors_1.EasCommandError('A metric argument is required in non-interactive mode. Available metrics: ' +
73
+ Object.keys(metricNames_1.METRIC_ALIASES).join(', '));
74
+ }
72
75
  else {
73
- log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
76
+ const choices = Object.entries(metricNames_1.METRIC_SHORT_NAMES).map(([fullName, displayName]) => ({
77
+ title: `${displayName} (${fullName})`,
78
+ value: fullName,
79
+ }));
80
+ metricName = await (0, prompts_1.selectAsync)('Select a metric', choices);
74
81
  }
75
- const metricNames = flags.metric?.length
76
- ? flags.metric.map(metricNames_1.resolveMetricName)
77
- : DEFAULT_METRICS;
82
+ const orderBy = (0, fetchEvents_1.resolveOrderBy)(flags.sort);
78
83
  const { daysBack, startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
84
+ const platform = (0, platforms_1.appObservePlatformFromFlag)(flags.platform);
79
85
  const platforms = (0, platforms_1.appPlatformsFromFlag)(flags.platform);
80
- const { metricsMap, buildNumbersMap, updateIdsMap, totalEventCounts } = await (0, fetchMetrics_1.fetchObserveMetricsAsync)(graphqlClient, projectId, metricNames, platforms, startTime, endTime);
81
- const argumentsStat = flags.stat?.length
82
- ? Array.from(new Set(flags.stat.map(formatMetrics_1.resolveStatKey)))
83
- : undefined;
86
+ const [{ events, pageInfo }, totalEventCount] = await Promise.all([
87
+ (0, fetchEvents_1.fetchObserveEventsAsync)(graphqlClient, projectId, {
88
+ metricName,
89
+ orderBy,
90
+ limit: flags.limit ?? DEFAULT_EVENTS_LIMIT,
91
+ ...(flags.after && { after: flags.after }),
92
+ startTime,
93
+ endTime,
94
+ platform,
95
+ appVersion: flags['app-version'],
96
+ updateId: flags['update-id'],
97
+ }),
98
+ (0, fetchEvents_1.fetchTotalEventCountAsync)(graphqlClient, projectId, metricName, platforms, startTime, endTime),
99
+ ]);
84
100
  if (flags.json) {
85
- const stats = argumentsStat ?? DEFAULT_STATS_JSON;
86
- (0, json_1.printJsonOnlyOutput)((0, formatMetrics_1.buildObserveMetricsJson)(metricsMap, metricNames, stats, totalEventCounts, buildNumbersMap, updateIdsMap));
101
+ (0, json_1.printJsonOnlyOutput)((0, formatEvents_1.buildObserveEventsJson)(events, pageInfo));
87
102
  }
88
103
  else {
89
- const stats = argumentsStat ?? DEFAULT_STATS_TABLE;
90
104
  log_1.default.addNewLineIfNone();
91
- log_1.default.log((0, formatMetrics_1.buildObserveMetricsTable)(metricsMap, metricNames, stats, {
105
+ log_1.default.log((0, formatEvents_1.buildObserveEventsTable)(events, pageInfo, {
106
+ metricName,
92
107
  daysBack,
93
- buildNumbersMap,
94
- totalEventCounts,
108
+ startTime,
109
+ endTime,
110
+ totalEventCount,
95
111
  }));
96
112
  }
97
113
  }
@@ -1,6 +1,5 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export default class ObserveRoutes extends EasCommand {
3
- static hidden: boolean;
4
3
  static description: string;
5
4
  static flags: {
6
5
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
@@ -19,7 +19,6 @@ const STAT_OPTIONS = ['median', 'med', 'p90', 'count', 'event_count', 'eventCoun
19
19
  const DEFAULT_STATS_TABLE = ['median', 'count'];
20
20
  const DEFAULT_STATS_JSON = ['median', 'p90', 'count'];
21
21
  class ObserveRoutes extends EasCommand_1.default {
22
- static hidden = true;
23
22
  static description = 'display app navigation route metrics (Cold TTR, Warm TTR, TTI) grouped by route name';
24
23
  static flags = {
25
24
  ...flags_2.ObservePlatformFlag,
@@ -70,9 +69,6 @@ class ObserveRoutes extends EasCommand_1.default {
70
69
  if (flags.json) {
71
70
  (0, json_1.enableJsonOutput)();
72
71
  }
73
- else {
74
- log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
75
- }
76
72
  const metricNames = flags.metric?.length
77
73
  ? Array.from(new Set(flags.metric.map(metricNames_1.resolveNavigationMetricName)))
78
74
  : formatNavigationRoutes_1.NAVIGATION_METRIC_NAMES;
@@ -1,6 +1,5 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export default class ObserveVersions extends EasCommand {
3
- static hidden: boolean;
4
3
  static description: string;
5
4
  static flags: {
6
5
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
@@ -12,7 +12,6 @@ const resolveProjectContext_1 = require("../../observe/resolveProjectContext");
12
12
  const startAndEndTime_1 = require("../../observe/startAndEndTime");
13
13
  const json_1 = require("../../utils/json");
14
14
  class ObserveVersions extends EasCommand_1.default {
15
- static hidden = true;
16
15
  static description = 'display app versions with build and update details';
17
16
  static flags = {
18
17
  ...flags_2.ObservePlatformFlag,
@@ -39,9 +38,6 @@ class ObserveVersions extends EasCommand_1.default {
39
38
  if (flags.json) {
40
39
  (0, json_1.enableJsonOutput)();
41
40
  }
42
- else {
43
- log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
44
- }
45
41
  const { startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
46
42
  const platforms = (0, platforms_1.appPlatformsFromFlag)(flags.platform);
47
43
  const results = await (0, fetchVersions_1.fetchObserveVersionsAsync)(graphqlClient, projectId, platforms, startTime, endTime);
@@ -0,0 +1,12 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class SimulatorExec extends EasCommand {
3
+ static hidden: boolean;
4
+ static description: string;
5
+ static strict: boolean;
6
+ static contextDefinition: {
7
+ projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
8
+ };
9
+ private isRunningSubprocess;
10
+ runAsync(): Promise<void>;
11
+ protected catch(err: Error): Promise<any>;
12
+ }