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.
- package/README.md +371 -100
- package/build/commands/go.d.ts +1 -0
- package/build/commands/go.js +29 -1
- package/build/commands/observe/events.d.ts +3 -3
- package/build/commands/observe/events.js +69 -51
- package/build/commands/observe/{logs.d.ts → metrics-summary.d.ts} +3 -11
- package/build/commands/observe/metrics-summary.js +95 -0
- package/build/commands/observe/metrics.d.ts +8 -3
- package/build/commands/observe/metrics.js +63 -47
- package/build/commands/observe/routes.d.ts +0 -1
- package/build/commands/observe/routes.js +0 -4
- package/build/commands/observe/versions.d.ts +0 -1
- package/build/commands/observe/versions.js +0 -4
- package/build/commands/simulator/exec.d.ts +12 -0
- package/build/commands/simulator/exec.js +42 -0
- package/build/commands/simulator/get.d.ts +2 -1
- package/build/commands/simulator/get.js +13 -7
- package/build/commands/simulator/start.d.ts +3 -0
- package/build/commands/simulator/start.js +65 -5
- package/build/commands/simulator/stop.d.ts +2 -1
- package/build/commands/simulator/stop.js +16 -9
- package/build/commands/update/embedded/delete.d.ts +15 -0
- package/build/commands/update/embedded/delete.js +55 -0
- package/build/commands/update/embedded/list.d.ts +19 -0
- package/build/commands/update/embedded/list.js +132 -0
- package/build/commands/update/embedded/upload.d.ts +20 -0
- package/build/commands/update/embedded/upload.js +129 -0
- package/build/commands/update/embedded/view.d.ts +17 -0
- package/build/commands/update/embedded/view.js +75 -0
- package/build/graphql/client.js +1 -0
- package/build/graphql/generated.d.ts +434 -4
- package/build/graphql/generated.js +35 -1
- package/build/graphql/mutations/EmbeddedUpdateAssetMutation.d.ts +13 -0
- package/build/graphql/mutations/EmbeddedUpdateAssetMutation.js +32 -0
- package/build/graphql/mutations/EmbeddedUpdateMutation.d.ts +19 -0
- package/build/graphql/mutations/EmbeddedUpdateMutation.js +51 -0
- package/build/graphql/queries/EmbeddedUpdateQuery.d.ts +18 -0
- package/build/graphql/queries/EmbeddedUpdateQuery.js +81 -0
- package/build/graphql/queries/WorkflowRunQuery.d.ts +2 -1
- package/build/graphql/queries/WorkflowRunQuery.js +19 -6
- package/build/observe/formatCustomEvents.js +5 -5
- package/build/observe/metricNames.js +2 -0
- package/build/simulator/env.d.ts +7 -0
- package/build/simulator/env.js +44 -0
- package/build/simulator/utils.d.ts +3 -1
- package/build/simulator/utils.js +26 -7
- package/build/update/embeddedManifest.d.ts +3 -0
- package/build/update/embeddedManifest.js +28 -0
- package/oclif.manifest.json +2803 -2309
- package/package.json +6 -6
- package/build/commands/observe/logs.js +0 -141
package/build/commands/go.d.ts
CHANGED
|
@@ -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;
|
package/build/commands/go.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
25
|
-
description: '
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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,
|
|
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,
|
|
110
|
-
|
|
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
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
|
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
|
|
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
|
|
36
|
-
static
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
|
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 {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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,
|
|
105
|
+
log_1.default.log((0, formatEvents_1.buildObserveEventsTable)(events, pageInfo, {
|
|
106
|
+
metricName,
|
|
92
107
|
daysBack,
|
|
93
|
-
|
|
94
|
-
|
|
108
|
+
startTime,
|
|
109
|
+
endTime,
|
|
110
|
+
totalEventCount,
|
|
95
111
|
}));
|
|
96
112
|
}
|
|
97
113
|
}
|
|
@@ -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;
|
|
@@ -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
|
+
}
|