eas-cli 18.5.0 → 18.6.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 +88 -88
- package/build/commandUtils/pagination.d.ts +2 -1
- package/build/commandUtils/pagination.js +3 -2
- package/build/commands/deploy/index.js +18 -2
- package/build/commands/metadata/pull.d.ts +1 -1
- package/build/commands/metadata/pull.js +2 -4
- package/build/commands/metadata/push.d.ts +1 -1
- package/build/commands/metadata/push.js +2 -4
- package/build/commands/observe/events.d.ts +27 -0
- package/build/commands/observe/events.js +140 -0
- package/build/commands/observe/metrics.d.ts +21 -0
- package/build/commands/observe/metrics.js +111 -0
- package/build/commands/observe/versions.d.ts +19 -0
- package/build/commands/observe/versions.js +69 -0
- package/build/credentials/ios/IosCredentialsProvider.js +8 -4
- package/build/credentials/ios/utils/provisioningProfile.d.ts +1 -0
- package/build/credentials/ios/utils/provisioningProfile.js +15 -1
- package/build/graphql/generated.d.ts +634 -61
- package/build/graphql/generated.js +11 -9
- package/build/graphql/queries/ObserveQuery.d.ts +35 -0
- package/build/graphql/queries/ObserveQuery.js +109 -0
- package/build/graphql/types/Observe.d.ts +3 -0
- package/build/graphql/types/Observe.js +84 -0
- package/build/metadata/apple/config/reader.d.ts +9 -1
- package/build/metadata/apple/config/reader.js +25 -0
- package/build/metadata/apple/config/writer.d.ts +7 -1
- package/build/metadata/apple/config/writer.js +44 -0
- package/build/metadata/apple/data.d.ts +2 -1
- package/build/metadata/apple/tasks/app-clip.d.ts +37 -0
- package/build/metadata/apple/tasks/app-clip.js +404 -0
- package/build/metadata/apple/tasks/index.js +2 -0
- package/build/metadata/apple/tasks/previews.js +16 -12
- package/build/metadata/apple/tasks/screenshots.js +15 -4
- package/build/metadata/apple/types.d.ts +28 -1
- package/build/observe/fetchEvents.d.ts +27 -0
- package/build/observe/fetchEvents.js +83 -0
- package/build/observe/fetchMetrics.d.ts +11 -0
- package/build/observe/fetchMetrics.js +78 -0
- package/build/observe/fetchVersions.d.ts +7 -0
- package/build/observe/fetchVersions.js +31 -0
- package/build/observe/formatEvents.d.ts +31 -0
- package/build/observe/formatEvents.js +99 -0
- package/build/observe/formatMetrics.d.ts +38 -0
- package/build/observe/formatMetrics.js +206 -0
- package/build/observe/formatVersions.d.ts +32 -0
- package/build/observe/formatVersions.js +92 -0
- package/build/observe/metricNames.d.ts +4 -0
- package/build/observe/metricNames.js +33 -0
- package/build/observe/startAndEndTime.d.ts +18 -0
- package/build/observe/startAndEndTime.js +36 -0
- package/build/user/SessionManager.js +11 -0
- package/build/worker/upload.js +15 -5
- package/oclif.manifest.json +1782 -1306
- package/package.json +9 -6
- package/schema/metadata-0.json +177 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Interfaces } from '@oclif/core';
|
|
2
2
|
import { EasNonInteractiveAndJsonFlags } from './flags';
|
|
3
3
|
export declare const getPaginatedQueryOptions: (flags: Partial<Record<keyof typeof EasPaginatedQueryFlags | keyof typeof EasNonInteractiveAndJsonFlags, any>>) => PaginatedQueryOptions;
|
|
4
|
-
export declare const getLimitFlagWithCustomValues: ({ defaultTo, limit, }: {
|
|
4
|
+
export declare const getLimitFlagWithCustomValues: ({ defaultTo, limit, description, }: {
|
|
5
5
|
defaultTo: number;
|
|
6
6
|
limit: number;
|
|
7
|
+
description?: string;
|
|
7
8
|
}) => Interfaces.OptionFlag<number | undefined>;
|
|
8
9
|
export declare const EasPaginatedQueryFlags: {
|
|
9
10
|
offset: Interfaces.OptionFlag<number | undefined, Interfaces.CustomOptions>;
|
|
@@ -23,8 +23,9 @@ const parseFlagInputStringAsInteger = (input, flagName, lowerLimit, upperLimit)
|
|
|
23
23
|
}
|
|
24
24
|
return inputAsNumber;
|
|
25
25
|
};
|
|
26
|
-
const getLimitFlagWithCustomValues = ({ defaultTo, limit, }) => core_1.Flags.integer({
|
|
27
|
-
description:
|
|
26
|
+
const getLimitFlagWithCustomValues = ({ defaultTo, limit, description, }) => core_1.Flags.integer({
|
|
27
|
+
description: description ??
|
|
28
|
+
`The number of items to fetch each query. Defaults to ${defaultTo} and is capped at ${limit}.`,
|
|
28
29
|
// eslint-disable-next-line async-protect/async-suffix
|
|
29
30
|
parse: async (input) => parseFlagInputStringAsInteger(input, 'limit', 1, limit),
|
|
30
31
|
});
|
|
@@ -243,8 +243,24 @@ class WorkerDeploy extends EasCommand_1.default {
|
|
|
243
243
|
}
|
|
244
244
|
throw error;
|
|
245
245
|
}
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
let uploadError;
|
|
247
|
+
try {
|
|
248
|
+
await uploadAssetsAsync(assetFiles, deployResult);
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
uploadError = error;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
await finalizeDeployAsync(deployResult);
|
|
255
|
+
}
|
|
256
|
+
catch (finalizeError) {
|
|
257
|
+
if (!uploadError) {
|
|
258
|
+
throw finalizeError;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (uploadError) {
|
|
262
|
+
throw uploadError;
|
|
263
|
+
}
|
|
248
264
|
let deploymentAlias = null;
|
|
249
265
|
if (flags.aliasName) {
|
|
250
266
|
progress = (0, ora_1.ora)((0, chalk_1.default) `Assigning alias {bold ${flags.aliasName}} to deployment`).start();
|
|
@@ -2,8 +2,8 @@ import EasCommand from '../../commandUtils/EasCommand';
|
|
|
2
2
|
export default class MetadataPull extends EasCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
|
-
profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
5
|
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
6
|
+
profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
7
|
};
|
|
8
8
|
static contextDefinition: {
|
|
9
9
|
vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
|
|
@@ -8,6 +8,7 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
|
8
8
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
9
9
|
const configure_1 = require("../../build/configure");
|
|
10
10
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
11
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
11
12
|
const context_1 = require("../../credentials/context");
|
|
12
13
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
13
14
|
const download_1 = require("../../metadata/download");
|
|
@@ -20,10 +21,7 @@ class MetadataPull extends EasCommand_1.default {
|
|
|
20
21
|
char: 'e',
|
|
21
22
|
description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
|
22
23
|
}),
|
|
23
|
-
|
|
24
|
-
default: false,
|
|
25
|
-
description: 'Run the command in non-interactive mode.',
|
|
26
|
-
}),
|
|
24
|
+
...flags_1.EASNonInteractiveFlag,
|
|
27
25
|
};
|
|
28
26
|
static contextDefinition = {
|
|
29
27
|
...this.ContextOptions.ProjectConfig,
|
|
@@ -2,8 +2,8 @@ import EasCommand from '../../commandUtils/EasCommand';
|
|
|
2
2
|
export default class MetadataPush extends EasCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
|
-
profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
5
|
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
6
|
+
profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
7
|
};
|
|
8
8
|
static contextDefinition: {
|
|
9
9
|
vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
|
|
@@ -6,6 +6,7 @@ const eas_json_1 = require("@expo/eas-json");
|
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
7
|
const configure_1 = require("../../build/configure");
|
|
8
8
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
9
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
9
10
|
const context_1 = require("../../credentials/context");
|
|
10
11
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
11
12
|
const errors_1 = require("../../metadata/errors");
|
|
@@ -18,10 +19,7 @@ class MetadataPush extends EasCommand_1.default {
|
|
|
18
19
|
char: 'e',
|
|
19
20
|
description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
|
20
21
|
}),
|
|
21
|
-
|
|
22
|
-
default: false,
|
|
23
|
-
description: 'Run the command in non-interactive mode.',
|
|
24
|
-
}),
|
|
22
|
+
...flags_1.EASNonInteractiveFlag,
|
|
25
23
|
};
|
|
26
24
|
static contextDefinition = {
|
|
27
25
|
...this.ContextOptions.ProjectConfig,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import EasCommand from '../../commandUtils/EasCommand';
|
|
2
|
+
export default class ObserveEvents extends EasCommand {
|
|
3
|
+
static hidden: boolean;
|
|
4
|
+
static description: string;
|
|
5
|
+
static args: {
|
|
6
|
+
metric: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
sort: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
after: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined>;
|
|
15
|
+
start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
end: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
+
days: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
'app-version': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
'update-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
};
|
|
22
|
+
static contextDefinition: {
|
|
23
|
+
loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
|
|
24
|
+
projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
|
|
25
|
+
};
|
|
26
|
+
runAsync(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
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 errors_1 = require("../../commandUtils/errors");
|
|
7
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
8
|
+
const pagination_1 = require("../../commandUtils/pagination");
|
|
9
|
+
const generated_1 = require("../../graphql/generated");
|
|
10
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
11
|
+
const fetchEvents_1 = require("../../observe/fetchEvents");
|
|
12
|
+
const metricNames_1 = require("../../observe/metricNames");
|
|
13
|
+
const formatEvents_1 = require("../../observe/formatEvents");
|
|
14
|
+
const startAndEndTime_1 = require("../../observe/startAndEndTime");
|
|
15
|
+
const prompts_1 = require("../../prompts");
|
|
16
|
+
const json_1 = require("../../utils/json");
|
|
17
|
+
const DEFAULT_EVENTS_LIMIT = 10;
|
|
18
|
+
class ObserveEvents extends EasCommand_1.default {
|
|
19
|
+
static hidden = true;
|
|
20
|
+
static description = 'display individual app performance events ordered by metric value';
|
|
21
|
+
static args = {
|
|
22
|
+
metric: core_1.Args.string({
|
|
23
|
+
description: 'Metric to query (e.g. tti, cold_launch)',
|
|
24
|
+
required: false,
|
|
25
|
+
options: Object.keys(metricNames_1.METRIC_ALIASES),
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
static flags = {
|
|
29
|
+
sort: core_1.Flags.option({
|
|
30
|
+
description: 'Sort order for events',
|
|
31
|
+
options: Object.values(fetchEvents_1.EventsOrderPreset).map(s => s.toLowerCase()),
|
|
32
|
+
required: false,
|
|
33
|
+
default: fetchEvents_1.EventsOrderPreset.Oldest.valueOf().toLowerCase(),
|
|
34
|
+
})(),
|
|
35
|
+
platform: core_1.Flags.option({
|
|
36
|
+
description: 'Filter by platform',
|
|
37
|
+
options: Object.values(generated_1.AppObservePlatform).map(s => s.toLowerCase()),
|
|
38
|
+
})(),
|
|
39
|
+
after: core_1.Flags.string({
|
|
40
|
+
description: 'Cursor for pagination. Use the endCursor from a previous query to fetch the next page.',
|
|
41
|
+
}),
|
|
42
|
+
limit: (0, pagination_1.getLimitFlagWithCustomValues)({
|
|
43
|
+
defaultTo: DEFAULT_EVENTS_LIMIT,
|
|
44
|
+
limit: 100,
|
|
45
|
+
}),
|
|
46
|
+
start: core_1.Flags.string({
|
|
47
|
+
description: 'Start of time range (ISO date)',
|
|
48
|
+
exclusive: ['days'],
|
|
49
|
+
}),
|
|
50
|
+
end: core_1.Flags.string({
|
|
51
|
+
description: 'End of time range (ISO date)',
|
|
52
|
+
exclusive: ['days'],
|
|
53
|
+
}),
|
|
54
|
+
days: core_1.Flags.integer({
|
|
55
|
+
description: 'Show events from the last N days (mutually exclusive with --start/--end)',
|
|
56
|
+
min: 1,
|
|
57
|
+
exclusive: ['start', 'end'],
|
|
58
|
+
}),
|
|
59
|
+
'app-version': core_1.Flags.string({
|
|
60
|
+
description: 'Filter by app version',
|
|
61
|
+
}),
|
|
62
|
+
'update-id': core_1.Flags.string({
|
|
63
|
+
description: 'Filter by EAS update ID',
|
|
64
|
+
}),
|
|
65
|
+
'project-id': core_1.Flags.string({
|
|
66
|
+
description: 'EAS project ID (defaults to the project ID of the current directory)',
|
|
67
|
+
}),
|
|
68
|
+
...flags_1.EasNonInteractiveAndJsonFlags,
|
|
69
|
+
};
|
|
70
|
+
static contextDefinition = {
|
|
71
|
+
...this.ContextOptions.ProjectId,
|
|
72
|
+
...this.ContextOptions.LoggedIn,
|
|
73
|
+
};
|
|
74
|
+
async runAsync() {
|
|
75
|
+
const { flags, args } = await this.parse(ObserveEvents);
|
|
76
|
+
const { projectId: contextProjectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(ObserveEvents, {
|
|
77
|
+
nonInteractive: flags['non-interactive'],
|
|
78
|
+
});
|
|
79
|
+
const projectId = flags['project-id'] ?? contextProjectId;
|
|
80
|
+
if (flags.json) {
|
|
81
|
+
(0, json_1.enableJsonOutput)();
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
|
|
85
|
+
}
|
|
86
|
+
let metricName;
|
|
87
|
+
if (args.metric) {
|
|
88
|
+
metricName = (0, metricNames_1.resolveMetricName)(args.metric);
|
|
89
|
+
}
|
|
90
|
+
else if (flags['non-interactive']) {
|
|
91
|
+
throw new errors_1.EasCommandError('A metric argument is required in non-interactive mode. Available metrics: ' +
|
|
92
|
+
Object.keys(metricNames_1.METRIC_ALIASES).join(', '));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const choices = Object.entries(metricNames_1.METRIC_SHORT_NAMES).map(([fullName, displayName]) => ({
|
|
96
|
+
title: `${displayName} (${fullName})`,
|
|
97
|
+
value: fullName,
|
|
98
|
+
}));
|
|
99
|
+
metricName = await (0, prompts_1.selectAsync)('Select a metric', choices);
|
|
100
|
+
}
|
|
101
|
+
const orderBy = (0, fetchEvents_1.resolveOrderBy)(flags.sort);
|
|
102
|
+
const { daysBack, startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
|
|
103
|
+
const platform = flags.platform
|
|
104
|
+
? flags.platform === 'android'
|
|
105
|
+
? generated_1.AppObservePlatform.Android
|
|
106
|
+
: generated_1.AppObservePlatform.Ios
|
|
107
|
+
: undefined;
|
|
108
|
+
const platforms = platform
|
|
109
|
+
? [platform === generated_1.AppObservePlatform.Android ? generated_1.AppPlatform.Android : generated_1.AppPlatform.Ios]
|
|
110
|
+
: [generated_1.AppPlatform.Android, generated_1.AppPlatform.Ios];
|
|
111
|
+
const [{ events, pageInfo }, totalEventCount] = await Promise.all([
|
|
112
|
+
(0, fetchEvents_1.fetchObserveEventsAsync)(graphqlClient, projectId, {
|
|
113
|
+
metricName,
|
|
114
|
+
orderBy,
|
|
115
|
+
limit: flags.limit ?? DEFAULT_EVENTS_LIMIT,
|
|
116
|
+
...(flags.after && { after: flags.after }),
|
|
117
|
+
startTime,
|
|
118
|
+
endTime,
|
|
119
|
+
platform,
|
|
120
|
+
appVersion: flags['app-version'],
|
|
121
|
+
updateId: flags['update-id'],
|
|
122
|
+
}),
|
|
123
|
+
(0, fetchEvents_1.fetchTotalEventCountAsync)(graphqlClient, projectId, metricName, platforms, startTime, endTime),
|
|
124
|
+
]);
|
|
125
|
+
if (flags.json) {
|
|
126
|
+
(0, json_1.printJsonOnlyOutput)((0, formatEvents_1.buildObserveEventsJson)(events, pageInfo));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
log_1.default.addNewLineIfNone();
|
|
130
|
+
log_1.default.log((0, formatEvents_1.buildObserveEventsTable)(events, pageInfo, {
|
|
131
|
+
metricName,
|
|
132
|
+
daysBack,
|
|
133
|
+
startTime,
|
|
134
|
+
endTime,
|
|
135
|
+
totalEventCount,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.default = ObserveEvents;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import EasCommand from '../../commandUtils/EasCommand';
|
|
2
|
+
export default class ObserveMetrics extends EasCommand {
|
|
3
|
+
static hidden: boolean;
|
|
4
|
+
static description: string;
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
metric: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
stat: import("@oclif/core/lib/interfaces").OptionFlag<("min" | "max" | "median" | "average" | "p80" | "p90" | "p99" | "eventCount")[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
end: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
days: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
static contextDefinition: {
|
|
17
|
+
loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
|
|
18
|
+
projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
|
|
19
|
+
};
|
|
20
|
+
runAsync(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
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 generated_1 = require("../../graphql/generated");
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
9
|
+
const fetchMetrics_1 = require("../../observe/fetchMetrics");
|
|
10
|
+
const formatMetrics_1 = require("../../observe/formatMetrics");
|
|
11
|
+
const metricNames_1 = require("../../observe/metricNames");
|
|
12
|
+
const startAndEndTime_1 = require("../../observe/startAndEndTime");
|
|
13
|
+
const json_1 = require("../../utils/json");
|
|
14
|
+
const DEFAULT_METRICS = [
|
|
15
|
+
'expo.app_startup.cold_launch_time',
|
|
16
|
+
'expo.app_startup.warm_launch_time',
|
|
17
|
+
'expo.app_startup.tti',
|
|
18
|
+
'expo.app_startup.ttr',
|
|
19
|
+
'expo.app_startup.bundle_load_time',
|
|
20
|
+
];
|
|
21
|
+
const DEFAULT_STATS_TABLE = ['median', 'eventCount'];
|
|
22
|
+
const DEFAULT_STATS_JSON = [
|
|
23
|
+
'min',
|
|
24
|
+
'median',
|
|
25
|
+
'max',
|
|
26
|
+
'average',
|
|
27
|
+
'p80',
|
|
28
|
+
'p90',
|
|
29
|
+
'p99',
|
|
30
|
+
'eventCount',
|
|
31
|
+
];
|
|
32
|
+
class ObserveMetrics extends EasCommand_1.default {
|
|
33
|
+
static hidden = true;
|
|
34
|
+
static description = 'display app performance metrics grouped by app version';
|
|
35
|
+
static flags = {
|
|
36
|
+
platform: core_1.Flags.option({
|
|
37
|
+
description: 'Filter by platform',
|
|
38
|
+
options: Object.values(generated_1.AppObservePlatform).map(s => s.toLowerCase()),
|
|
39
|
+
})(),
|
|
40
|
+
metric: core_1.Flags.option({
|
|
41
|
+
description: 'Metric name to display (can be specified multiple times).',
|
|
42
|
+
multiple: true,
|
|
43
|
+
options: Object.keys(metricNames_1.METRIC_ALIASES),
|
|
44
|
+
})(),
|
|
45
|
+
stat: core_1.Flags.option({
|
|
46
|
+
description: 'Statistic to display per metric (can be specified multiple times)',
|
|
47
|
+
multiple: true,
|
|
48
|
+
options: DEFAULT_STATS_JSON,
|
|
49
|
+
})(),
|
|
50
|
+
start: core_1.Flags.string({
|
|
51
|
+
description: 'Start of time range for metrics data (ISO date).',
|
|
52
|
+
exclusive: ['days'],
|
|
53
|
+
}),
|
|
54
|
+
end: core_1.Flags.string({
|
|
55
|
+
description: 'End of time range for metrics data (ISO date).',
|
|
56
|
+
exclusive: ['days'],
|
|
57
|
+
}),
|
|
58
|
+
days: core_1.Flags.integer({
|
|
59
|
+
description: 'Show metrics from the last N days (mutually exclusive with --start/--end)',
|
|
60
|
+
min: 1,
|
|
61
|
+
exclusive: ['start', 'end'],
|
|
62
|
+
}),
|
|
63
|
+
'project-id': core_1.Flags.string({
|
|
64
|
+
description: 'EAS project ID (defaults to the project ID of the current directory)',
|
|
65
|
+
}),
|
|
66
|
+
...flags_1.EasNonInteractiveAndJsonFlags,
|
|
67
|
+
};
|
|
68
|
+
static contextDefinition = {
|
|
69
|
+
...this.ContextOptions.ProjectId,
|
|
70
|
+
...this.ContextOptions.LoggedIn,
|
|
71
|
+
};
|
|
72
|
+
async runAsync() {
|
|
73
|
+
const { flags } = await this.parse(ObserveMetrics);
|
|
74
|
+
const { projectId: contextProjectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(ObserveMetrics, {
|
|
75
|
+
nonInteractive: flags['non-interactive'],
|
|
76
|
+
});
|
|
77
|
+
const projectId = flags['project-id'] ?? contextProjectId;
|
|
78
|
+
if (flags.json) {
|
|
79
|
+
(0, json_1.enableJsonOutput)();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
|
|
83
|
+
}
|
|
84
|
+
const metricNames = flags.metric?.length
|
|
85
|
+
? flags.metric.map(metricNames_1.resolveMetricName)
|
|
86
|
+
: DEFAULT_METRICS;
|
|
87
|
+
const { daysBack, startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
|
|
88
|
+
const platforms = flags.platform
|
|
89
|
+
? [flags.platform === 'android' ? generated_1.AppPlatform.Android : generated_1.AppPlatform.Ios]
|
|
90
|
+
: [generated_1.AppPlatform.Android, generated_1.AppPlatform.Ios];
|
|
91
|
+
const { metricsMap, buildNumbersMap, updateIdsMap, totalEventCounts } = await (0, fetchMetrics_1.fetchObserveMetricsAsync)(graphqlClient, projectId, metricNames, platforms, startTime, endTime);
|
|
92
|
+
const argumentsStat = flags.stat?.length
|
|
93
|
+
? Array.from(new Set(flags.stat.map(formatMetrics_1.resolveStatKey)))
|
|
94
|
+
: undefined;
|
|
95
|
+
if (flags.json) {
|
|
96
|
+
const stats = argumentsStat ?? DEFAULT_STATS_JSON;
|
|
97
|
+
(0, json_1.printJsonOnlyOutput)((0, formatMetrics_1.buildObserveMetricsJson)(metricsMap, metricNames, stats, totalEventCounts));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const stats = argumentsStat ?? DEFAULT_STATS_TABLE;
|
|
101
|
+
log_1.default.addNewLineIfNone();
|
|
102
|
+
log_1.default.log((0, formatMetrics_1.buildObserveMetricsTable)(metricsMap, metricNames, stats, {
|
|
103
|
+
daysBack,
|
|
104
|
+
buildNumbersMap,
|
|
105
|
+
updateIdsMap,
|
|
106
|
+
totalEventCounts,
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.default = ObserveMetrics;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import EasCommand from '../../commandUtils/EasCommand';
|
|
2
|
+
export default class ObserveVersions extends EasCommand {
|
|
3
|
+
static hidden: boolean;
|
|
4
|
+
static description: string;
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
platform: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
start: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
end: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
days: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
'project-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
static contextDefinition: {
|
|
15
|
+
loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
|
|
16
|
+
projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
|
|
17
|
+
};
|
|
18
|
+
runAsync(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
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 generated_1 = require("../../graphql/generated");
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
9
|
+
const fetchVersions_1 = require("../../observe/fetchVersions");
|
|
10
|
+
const formatVersions_1 = require("../../observe/formatVersions");
|
|
11
|
+
const startAndEndTime_1 = require("../../observe/startAndEndTime");
|
|
12
|
+
const json_1 = require("../../utils/json");
|
|
13
|
+
class ObserveVersions extends EasCommand_1.default {
|
|
14
|
+
static hidden = true;
|
|
15
|
+
static description = 'display app versions with build and update details';
|
|
16
|
+
static flags = {
|
|
17
|
+
platform: core_1.Flags.option({
|
|
18
|
+
description: 'Filter by platform',
|
|
19
|
+
options: Object.values(generated_1.AppObservePlatform).map(s => s.toLowerCase()),
|
|
20
|
+
})(),
|
|
21
|
+
start: core_1.Flags.string({
|
|
22
|
+
description: 'Start of time range (ISO date)',
|
|
23
|
+
exclusive: ['days'],
|
|
24
|
+
}),
|
|
25
|
+
end: core_1.Flags.string({
|
|
26
|
+
description: 'End of time range (ISO date)',
|
|
27
|
+
exclusive: ['days'],
|
|
28
|
+
}),
|
|
29
|
+
days: core_1.Flags.integer({
|
|
30
|
+
description: 'Show versions from the last N days (mutually exclusive with --start/--end)',
|
|
31
|
+
min: 1,
|
|
32
|
+
exclusive: ['start', 'end'],
|
|
33
|
+
}),
|
|
34
|
+
'project-id': core_1.Flags.string({
|
|
35
|
+
description: 'EAS project ID (defaults to the project ID of the current directory)',
|
|
36
|
+
}),
|
|
37
|
+
...flags_1.EasNonInteractiveAndJsonFlags,
|
|
38
|
+
};
|
|
39
|
+
static contextDefinition = {
|
|
40
|
+
...this.ContextOptions.ProjectId,
|
|
41
|
+
...this.ContextOptions.LoggedIn,
|
|
42
|
+
};
|
|
43
|
+
async runAsync() {
|
|
44
|
+
const { flags } = await this.parse(ObserveVersions);
|
|
45
|
+
const { projectId: contextProjectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(ObserveVersions, {
|
|
46
|
+
nonInteractive: flags['non-interactive'],
|
|
47
|
+
});
|
|
48
|
+
const projectId = flags['project-id'] ?? contextProjectId;
|
|
49
|
+
if (flags.json) {
|
|
50
|
+
(0, json_1.enableJsonOutput)();
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
log_1.default.warn('EAS Observe is in preview and subject to breaking changes.');
|
|
54
|
+
}
|
|
55
|
+
const { startTime, endTime } = (0, startAndEndTime_1.resolveTimeRange)(flags);
|
|
56
|
+
const platforms = flags.platform
|
|
57
|
+
? [flags.platform === 'android' ? generated_1.AppPlatform.Android : generated_1.AppPlatform.Ios]
|
|
58
|
+
: [generated_1.AppPlatform.Android, generated_1.AppPlatform.Ios];
|
|
59
|
+
const results = await (0, fetchVersions_1.fetchObserveVersionsAsync)(graphqlClient, projectId, platforms, startTime, endTime);
|
|
60
|
+
if (flags.json) {
|
|
61
|
+
(0, json_1.printJsonOnlyOutput)((0, formatVersions_1.buildObserveVersionsJson)(results));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
log_1.default.addNewLineIfNone();
|
|
65
|
+
log_1.default.log((0, formatVersions_1.buildObserveVersionsTable)(results));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.default = ObserveVersions;
|
|
@@ -112,6 +112,7 @@ class IosCredentialsProvider {
|
|
|
112
112
|
}
|
|
113
113
|
assertProvisioningProfileType(provisioningProfile, targetName) {
|
|
114
114
|
const isAdHoc = (0, provisioningProfile_1.isAdHocProfile)(provisioningProfile);
|
|
115
|
+
const isDevelopment = (0, provisioningProfile_1.isDevelopmentProfile)(provisioningProfile);
|
|
115
116
|
const isEnterprise = (0, provisioningProfile_1.isEnterpriseUniversalProfile)(provisioningProfile);
|
|
116
117
|
if (this.options.distribution === 'internal') {
|
|
117
118
|
if (this.options.enterpriseProvisioning === 'universal' && !isEnterprise) {
|
|
@@ -120,12 +121,15 @@ class IosCredentialsProvider {
|
|
|
120
121
|
else if (this.options.enterpriseProvisioning === 'adhoc' && !isAdHoc) {
|
|
121
122
|
throw new Error(`You must use an adhoc provisioning profile${targetName ? ` (target '${targetName})'` : ''} for internal distribution if you specified "enterpriseProvisioning": "adhoc" in eas.json`);
|
|
122
123
|
}
|
|
123
|
-
else if (!this.options.enterpriseProvisioning &&
|
|
124
|
-
|
|
124
|
+
else if (!this.options.enterpriseProvisioning &&
|
|
125
|
+
!isEnterprise &&
|
|
126
|
+
!isAdHoc &&
|
|
127
|
+
!isDevelopment) {
|
|
128
|
+
throw new Error(`You must use an adhoc or development provisioning profile${targetName ? ` (target '${targetName})'` : ''} for internal distribution.`);
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
|
-
else if (isAdHoc) {
|
|
128
|
-
throw new Error(`You can't use an adhoc provisioning profile${targetName ? ` (target '${targetName}')` : ''} for app store distribution.`);
|
|
131
|
+
else if (isAdHoc || isDevelopment) {
|
|
132
|
+
throw new Error(`You can't use ${isAdHoc ? 'an adhoc' : 'a development'} provisioning profile${targetName ? ` (target '${targetName}')` : ''} for app store distribution.`);
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
}
|
|
@@ -6,6 +6,7 @@ interface AppleTeam {
|
|
|
6
6
|
export declare function readAppleTeam(dataBase64: string): AppleTeam;
|
|
7
7
|
export declare function readProfileName(dataBase64: string): string;
|
|
8
8
|
export declare function isAdHocProfile(dataBase64: string): boolean;
|
|
9
|
+
export declare function isDevelopmentProfile(dataBase64: string): boolean;
|
|
9
10
|
export declare function isEnterpriseUniversalProfile(dataBase64: string): boolean;
|
|
10
11
|
export declare function parse(dataBase64: string): PlistObject;
|
|
11
12
|
export {};
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.readAppleTeam = readAppleTeam;
|
|
4
4
|
exports.readProfileName = readProfileName;
|
|
5
5
|
exports.isAdHocProfile = isAdHocProfile;
|
|
6
|
+
exports.isDevelopmentProfile = isDevelopmentProfile;
|
|
6
7
|
exports.isEnterpriseUniversalProfile = isEnterpriseUniversalProfile;
|
|
7
8
|
exports.parse = parse;
|
|
8
9
|
const tslib_1 = require("tslib");
|
|
@@ -23,7 +24,20 @@ function readProfileName(dataBase64) {
|
|
|
23
24
|
function isAdHocProfile(dataBase64) {
|
|
24
25
|
const profilePlist = parse(dataBase64);
|
|
25
26
|
const provisionedDevices = profilePlist['ProvisionedDevices'];
|
|
26
|
-
|
|
27
|
+
if (!Array.isArray(provisionedDevices)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const entitlements = profilePlist['Entitlements'];
|
|
31
|
+
return !entitlements?.['get-task-allow'];
|
|
32
|
+
}
|
|
33
|
+
function isDevelopmentProfile(dataBase64) {
|
|
34
|
+
const profilePlist = parse(dataBase64);
|
|
35
|
+
const provisionedDevices = profilePlist['ProvisionedDevices'];
|
|
36
|
+
if (!Array.isArray(provisionedDevices)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const entitlements = profilePlist['Entitlements'];
|
|
40
|
+
return !!entitlements?.['get-task-allow'];
|
|
27
41
|
}
|
|
28
42
|
function isEnterpriseUniversalProfile(dataBase64) {
|
|
29
43
|
const profilePlist = parse(dataBase64);
|